tailkitty 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tailkitty-0.1.0/.gitignore +11 -0
- tailkitty-0.1.0/.mise.toml +60 -0
- tailkitty-0.1.0/.python-version +2 -0
- tailkitty-0.1.0/AGENTS.md +167 -0
- tailkitty-0.1.0/BUILDING.md +42 -0
- tailkitty-0.1.0/CHANGELOG.md +11 -0
- tailkitty-0.1.0/COMPARISON.md +22 -0
- tailkitty-0.1.0/ITERATIONS.md +135 -0
- tailkitty-0.1.0/LICENSE +28 -0
- tailkitty-0.1.0/PKG-INFO +391 -0
- tailkitty-0.1.0/README.md +367 -0
- tailkitty-0.1.0/SECURITY.md +18 -0
- tailkitty-0.1.0/THIRD_PARTY_NOTICES.md +13 -0
- tailkitty-0.1.0/hatch_build.py +52 -0
- tailkitty-0.1.0/pyproject.toml +73 -0
- tailkitty-0.1.0/scripts/__init__.py +1 -0
- tailkitty-0.1.0/scripts/build_binary.py +202 -0
- tailkitty-0.1.0/scripts/build_wheels.py +67 -0
- tailkitty-0.1.0/scripts/smoke_wheel.py +59 -0
- tailkitty-0.1.0/scripts/targets.py +95 -0
- tailkitty-0.1.0/scripts/verify_wheel.py +113 -0
- tailkitty-0.1.0/src/tailkitty/__init__.py +40 -0
- tailkitty-0.1.0/src/tailkitty/__main__.py +5 -0
- tailkitty-0.1.0/src/tailkitty/backend.py +107 -0
- tailkitty-0.1.0/src/tailkitty/bundle.py +139 -0
- tailkitty-0.1.0/src/tailkitty/cli.py +82 -0
- tailkitty-0.1.0/src/tailkitty/client.py +150 -0
- tailkitty-0.1.0/src/tailkitty/constants.py +7 -0
- tailkitty-0.1.0/src/tailkitty/derp.py +140 -0
- tailkitty-0.1.0/src/tailkitty/destination.py +66 -0
- tailkitty-0.1.0/src/tailkitty/diagnostics.py +38 -0
- tailkitty-0.1.0/src/tailkitty/process.py +322 -0
- tailkitty-0.1.0/src/tailkitty/py.typed +1 -0
- tailkitty-0.1.0/src/tailkitty/token.py +259 -0
- tailkitty-0.1.0/tests/test_backend.py +53 -0
- tailkitty-0.1.0/tests/test_bundle.py +111 -0
- tailkitty-0.1.0/tests/test_cli.py +27 -0
- tailkitty-0.1.0/tests/test_derp.py +60 -0
- tailkitty-0.1.0/tests/test_destination.py +32 -0
- tailkitty-0.1.0/tests/test_module.py +14 -0
- tailkitty-0.1.0/tests/test_process.py +88 -0
- tailkitty-0.1.0/tests/test_project.py +38 -0
- tailkitty-0.1.0/tests/test_targets.py +19 -0
- tailkitty-0.1.0/tests/test_token.py +94 -0
- tailkitty-0.1.0/tests/test_token_validation.py +32 -0
- tailkitty-0.1.0/uv.lock +692 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
[tools]
|
|
2
|
+
python = "3.13.11"
|
|
3
|
+
go = "1.26.5"
|
|
4
|
+
uv = "0.12.7"
|
|
5
|
+
|
|
6
|
+
[env]
|
|
7
|
+
UV_CACHE_DIR = "{{config_root}}/.cache/uv"
|
|
8
|
+
|
|
9
|
+
[tasks.setup]
|
|
10
|
+
description = "Install Python dependencies and the interoperable Tailcat backend"
|
|
11
|
+
run = [
|
|
12
|
+
"uv sync --all-groups",
|
|
13
|
+
"mise run backend",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[tasks.backend]
|
|
17
|
+
description = "Build the upstream Tailcat data-plane helper"
|
|
18
|
+
run = "uv run python -m scripts.build_binary build --output .tools/bin"
|
|
19
|
+
|
|
20
|
+
[tasks.bundle]
|
|
21
|
+
description = "Build a bundled executable for the host platform"
|
|
22
|
+
run = "uv run python -m scripts.build_binary build --target host --output src/tailkitty/bin"
|
|
23
|
+
|
|
24
|
+
[tasks.bundle-verify]
|
|
25
|
+
description = "Verify the bundled executable and integrity manifest"
|
|
26
|
+
run = "uv run python -m scripts.build_binary verify --output src/tailkitty/bin"
|
|
27
|
+
|
|
28
|
+
[tasks.bundle-clean]
|
|
29
|
+
description = "Remove generated bundled executable files"
|
|
30
|
+
run = "uv run python -m scripts.build_binary clean --output src/tailkitty/bin"
|
|
31
|
+
|
|
32
|
+
[tasks.wheel]
|
|
33
|
+
description = "Build a platform wheel containing the host executable"
|
|
34
|
+
depends = ["bundle", "bundle-verify"]
|
|
35
|
+
run = "uv build --wheel"
|
|
36
|
+
|
|
37
|
+
[tasks.wheels]
|
|
38
|
+
description = "Build and verify all supported platform wheels"
|
|
39
|
+
run = "uv run python -m scripts.build_wheels"
|
|
40
|
+
|
|
41
|
+
[tasks.wheel-smoke]
|
|
42
|
+
description = "Install and inspect the bundled host wheel in an isolated environment"
|
|
43
|
+
run = "uv run python -m scripts.smoke_wheel"
|
|
44
|
+
|
|
45
|
+
[tasks.test]
|
|
46
|
+
description = "Run the Python test suite"
|
|
47
|
+
run = [
|
|
48
|
+
"uv run ruff check src tests scripts hatch_build.py",
|
|
49
|
+
"uv run ruff format --check src tests scripts hatch_build.py",
|
|
50
|
+
"uv run mypy src scripts",
|
|
51
|
+
"uv run pytest",
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
[tasks.tailkitty]
|
|
55
|
+
description = "Run Tailkitty"
|
|
56
|
+
run = "uv run tailkitty"
|
|
57
|
+
|
|
58
|
+
[tasks.tailcat]
|
|
59
|
+
description = "Run Tailkitty through its Tailcat-compatible alias"
|
|
60
|
+
run = "uv run tailcat"
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Repository instructions for coding agents
|
|
2
|
+
|
|
3
|
+
These instructions apply to the entire repository. They supplement the user request; they do not
|
|
4
|
+
override it.
|
|
5
|
+
|
|
6
|
+
## Start here
|
|
7
|
+
|
|
8
|
+
Read these files before making architectural, packaging, security, or release changes:
|
|
9
|
+
|
|
10
|
+
1. `README.md` for the product boundary and public behavior.
|
|
11
|
+
2. `SECURITY.md` for executable trust and authorization concerns.
|
|
12
|
+
3. `BUILDING.md` for the reproducible bundle and wheel pipeline.
|
|
13
|
+
4. `pyproject.toml` and `.mise.toml` for supported versions and canonical tasks.
|
|
14
|
+
|
|
15
|
+
Do not confuse Tailkitty with the separate `pytailcat` distribution on PyPI. This checkout is the
|
|
16
|
+
source of truth for Tailkitty; upstream Tailcat remains the data-plane source of truth.
|
|
17
|
+
|
|
18
|
+
## Architecture and non-negotiable boundaries
|
|
19
|
+
|
|
20
|
+
The project intentionally has two layers:
|
|
21
|
+
|
|
22
|
+
- The control plane is Python: token encoding/decoding, validation, DNS TXT lookup, DERP-map
|
|
23
|
+
resolution/cache, typed clients, diagnostics, and process lifecycle.
|
|
24
|
+
- The network data plane is the pinned upstream Go Tailcat executable: magicsock, userspace
|
|
25
|
+
WireGuard, DERP transport, and gVisor netstack.
|
|
26
|
+
|
|
27
|
+
Do not replace the data plane with a Python-only protocol that interoperates only with itself. Do
|
|
28
|
+
not silently fall back from a corrupt bundled executable to an unverified backend. Wire
|
|
29
|
+
compatibility and fail-closed bundle discovery are core requirements.
|
|
30
|
+
|
|
31
|
+
## Repository map
|
|
32
|
+
|
|
33
|
+
| Path | Responsibility |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| `src/tailkitty/token.py` | Tailcat CBOR/base64url wire format and DERP embedding |
|
|
36
|
+
| `src/tailkitty/destination.py` | Literal-token and DNS TXT destination resolution |
|
|
37
|
+
| `src/tailkitty/derp.py` | Validated, bounded, atomic DERP-map caching |
|
|
38
|
+
| `src/tailkitty/backend.py` | Backend precedence and command execution |
|
|
39
|
+
| `src/tailkitty/bundle.py` | Runtime manifest and executable integrity checks |
|
|
40
|
+
| `src/tailkitty/client.py` | Sync and asyncio client APIs |
|
|
41
|
+
| `src/tailkitty/process.py` | Managed server processes and low-level async execution |
|
|
42
|
+
| `src/tailkitty/cli.py` | Python-native commands and upstream pass-through |
|
|
43
|
+
| `src/tailkitty/constants.py` | Package, Go, module, and upstream Tailcat pins |
|
|
44
|
+
| `scripts/targets.py` | Supported build targets and wheel tags |
|
|
45
|
+
| `scripts/build_binary.py` | Reproducible cross-compilation and manifest creation |
|
|
46
|
+
| `scripts/build_wheels.py` | Isolated five-target wheel orchestration |
|
|
47
|
+
| `scripts/verify_wheel.py` | Wheel metadata, archive, binary, and RECORD verification |
|
|
48
|
+
| `hatch_build.py` | Platform-wheel build hook |
|
|
49
|
+
| `tests/` | Unit and subprocess behavior tests |
|
|
50
|
+
|
|
51
|
+
Public imports are curated in `src/tailkitty/__init__.py`. Adding a public API requires updating
|
|
52
|
+
that file, type annotations, tests, and README documentation.
|
|
53
|
+
|
|
54
|
+
## Environment and canonical commands
|
|
55
|
+
|
|
56
|
+
Use mise and uv; do not introduce a parallel virtualenv, dependency manager, or ad hoc Go version.
|
|
57
|
+
|
|
58
|
+
```console
|
|
59
|
+
mise install
|
|
60
|
+
uv sync --all-groups --locked
|
|
61
|
+
mise run test
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`mise run test` is the required local quality gate. It runs Ruff linting, Ruff formatting checks,
|
|
65
|
+
strict mypy, and pytest. During iteration, run the narrowest relevant test first, then run the full
|
|
66
|
+
gate before declaring completion.
|
|
67
|
+
|
|
68
|
+
Packaging changes also require:
|
|
69
|
+
|
|
70
|
+
```console
|
|
71
|
+
mise run bundle
|
|
72
|
+
mise run bundle-verify
|
|
73
|
+
mise run wheels
|
|
74
|
+
uv run python -m scripts.smoke_wheel dist/wheels/<host-wheel>.whl
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
For Python-version compatibility changes, test the minimum version:
|
|
78
|
+
|
|
79
|
+
```console
|
|
80
|
+
uv run --isolated --python 3.11 --all-groups pytest
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Public DERP relays are external and can be unavailable or rate-limited. Keep unit tests deterministic
|
|
84
|
+
and do not make the default test suite depend on a live relay. Report live integration timeouts
|
|
85
|
+
honestly rather than treating them as proof of a local regression or success.
|
|
86
|
+
|
|
87
|
+
## Version and build invariants
|
|
88
|
+
|
|
89
|
+
- `TAILKITTY_VERSION` must match `[project].version` in `pyproject.toml`.
|
|
90
|
+
- `GO_VERSION` must match `[tools].go` in `.mise.toml` exactly.
|
|
91
|
+
- `TAILCAT_VERSION` must remain an immutable upstream version or pseudo-version.
|
|
92
|
+
- Bundle builds must use the exact Go toolchain with `GOTOOLCHAIN=local`.
|
|
93
|
+
- Keep `CGO_ENABLED=0`, `-trimpath`, `-buildvcs=false`, the empty build ID, stripped symbols, and
|
|
94
|
+
baseline CPU feature levels unless a documented compatibility decision changes them.
|
|
95
|
+
- Every platform wheel must be non-pure and tagged for exactly one supported target.
|
|
96
|
+
- Source distributions and pure-Python fallback wheels must contain no generated executable or
|
|
97
|
+
bundle manifest.
|
|
98
|
+
- Do not invent a platform tag. Update `scripts/targets.py`, build validation, CI, tests, and docs as
|
|
99
|
+
one change when adding a target.
|
|
100
|
+
|
|
101
|
+
## Backend and security invariants
|
|
102
|
+
|
|
103
|
+
Backend priority is:
|
|
104
|
+
|
|
105
|
+
1. `TAILKITTY_BACKEND`, which must be executable or fail immediately.
|
|
106
|
+
2. A verified, runtime-compatible bundled executable.
|
|
107
|
+
3. `.tools/bin/tailcat`, followed by the legacy `.tools/bin/tailcat-go` path.
|
|
108
|
+
4. `tailcat-go` on `PATH`.
|
|
109
|
+
|
|
110
|
+
Preserve these behaviors:
|
|
111
|
+
|
|
112
|
+
- A present but invalid bundle is an integrity error; it must not trigger fallback.
|
|
113
|
+
- Manifest filenames cannot contain paths, and bundled executables cannot be symlinks.
|
|
114
|
+
- Runtime checks cover schema, module, revision, platform, size, and SHA-256.
|
|
115
|
+
- `allow=None` preserves upstream's allow-all behavior; `allow=[]` must become `--allow=none`.
|
|
116
|
+
- Timeout and cancellation paths must terminate and reap child processes.
|
|
117
|
+
- Cache files remain bounded, private, atomically replaced, and safe to use stale after refresh
|
|
118
|
+
failure.
|
|
119
|
+
- Never log saved private keys or embed real active connection addresses in fixtures or docs.
|
|
120
|
+
|
|
121
|
+
## CLI compatibility
|
|
122
|
+
|
|
123
|
+
The Python CLI owns only `parse`, `resolve`, `doctor`, `--version`, and top-level help. All other
|
|
124
|
+
argument sequences must pass unchanged to the upstream executable, including no arguments.
|
|
125
|
+
|
|
126
|
+
When changing command dispatch, test both the Python-native commands and an arbitrary upstream
|
|
127
|
+
argument sequence. Do not add a Python subcommand whose name silently shadows an upstream command
|
|
128
|
+
without an explicit compatibility decision.
|
|
129
|
+
|
|
130
|
+
## Code and test conventions
|
|
131
|
+
|
|
132
|
+
- Support Python 3.11 and newer.
|
|
133
|
+
- Keep complete annotations and strict-mypy compatibility.
|
|
134
|
+
- Prefer standard-library types and small typed dataclasses over untyped dictionaries at public
|
|
135
|
+
boundaries.
|
|
136
|
+
- Keep synchronous and asyncio behavior aligned, especially timeout, cancellation, and cleanup.
|
|
137
|
+
- Validate external input early with domain-specific exceptions (`TokenError`, `DestinationError`,
|
|
138
|
+
`DerpMapError`, `BundleError`, or `BackendNotFound`).
|
|
139
|
+
- Add regression tests for bug fixes. Avoid weakening a safety check merely to satisfy a fixture.
|
|
140
|
+
- Use temporary directories in tests; never depend on or overwrite a developer's saved Tailcat
|
|
141
|
+
keys, cache, bundle, or configured backend.
|
|
142
|
+
- Keep Ruff's 100-character line length and run formatting rather than hand-aligning code.
|
|
143
|
+
|
|
144
|
+
## Generated files and release safety
|
|
145
|
+
|
|
146
|
+
Do not manually edit or commit generated files under:
|
|
147
|
+
|
|
148
|
+
- `src/tailkitty/bin/`
|
|
149
|
+
- `dist/`
|
|
150
|
+
- `.tools/bin/`
|
|
151
|
+
- cache, virtualenv, or `__pycache__` directories
|
|
152
|
+
|
|
153
|
+
Use the scripts and mise tasks that own those artifacts. Publish only the `tailkitty` distribution;
|
|
154
|
+
the `pytailcat` name belongs to another project. Before a release, verify project URLs and the `pypi`
|
|
155
|
+
GitHub environment, build all five wheels plus the source distribution, smoke-test the host wheel,
|
|
156
|
+
and retain checksums and provenance attestations.
|
|
157
|
+
|
|
158
|
+
## Definition of done
|
|
159
|
+
|
|
160
|
+
A change is complete when:
|
|
161
|
+
|
|
162
|
+
1. The implementation respects the Python/native boundary and security invariants.
|
|
163
|
+
2. Focused regression tests cover new behavior or the repaired failure.
|
|
164
|
+
3. Public behavior and types are documented where users will find them.
|
|
165
|
+
4. `mise run test` passes.
|
|
166
|
+
5. Packaging changes pass the full wheel matrix and host installation smoke test.
|
|
167
|
+
6. Remaining external limitations or unverified assumptions are stated explicitly.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Building bundled wheels
|
|
2
|
+
|
|
3
|
+
The environment is fully pinned by mise: Python 3.13.11, Go 1.26.5, and uv 0.12.7.
|
|
4
|
+
|
|
5
|
+
```console
|
|
6
|
+
mise install
|
|
7
|
+
uv sync --all-groups --locked
|
|
8
|
+
mise run test
|
|
9
|
+
mise run wheels
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
`mise run wheels` cross-compiles the exact Tailcat revision in `constants.py` for five targets,
|
|
13
|
+
stages each executable separately, builds a correctly tagged non-pure wheel, and verifies its
|
|
14
|
+
archive paths, executable format, bundle digest, and every wheel `RECORD` entry. Build inputs use
|
|
15
|
+
`CGO_ENABLED=0`, `-trimpath`, no VCS metadata, no Go build ID, baseline CPU levels, and the exact
|
|
16
|
+
mise-managed Go compiler. Dependency downloads receive bounded retries for transient CI failures.
|
|
17
|
+
|
|
18
|
+
Build one target with:
|
|
19
|
+
|
|
20
|
+
```console
|
|
21
|
+
uv run python -m scripts.build_wheels --target linux-x86_64 --output dist/wheels
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Install-test the wheel matching the current host with:
|
|
25
|
+
|
|
26
|
+
```console
|
|
27
|
+
uv run python -m scripts.smoke_wheel path/to/tailkitty-*.whl
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The wheel matrix is:
|
|
31
|
+
|
|
32
|
+
| Build target | Wheel platform tag | Executable |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| `macos-arm64` | `macosx_12_0_arm64` | Mach-O |
|
|
35
|
+
| `macos-x86_64` | `macosx_12_0_x86_64` | Mach-O |
|
|
36
|
+
| `linux-x86_64` | `manylinux_2_17_x86_64` | ELF |
|
|
37
|
+
| `linux-aarch64` | `manylinux_2_17_aarch64` | ELF |
|
|
38
|
+
| `windows-x86_64` | `win_amd64` | PE |
|
|
39
|
+
|
|
40
|
+
The release workflow rebuilds the matrix, creates a binary-free source distribution, generates
|
|
41
|
+
checksums, creates GitHub build-provenance attestations, and uses PyPI trusted publishing. Configure
|
|
42
|
+
the `pypi` GitHub environment before enabling it.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 - unreleased
|
|
4
|
+
|
|
5
|
+
- Launch under the Tailkitty distribution, import, and primary CLI name.
|
|
6
|
+
- Implement Tailcat token parsing, validation, resolution, DNS destination lookup, and DERP caching
|
|
7
|
+
in Python.
|
|
8
|
+
- Add typed synchronous and asyncio client/server process APIs.
|
|
9
|
+
- Bundle a pinned upstream data plane in verified wheels for five desktop/server targets.
|
|
10
|
+
- Add structured backend diagnostics, reproducible builds, artifact verification, isolated wheel
|
|
11
|
+
smoke tests, CI, release provenance, and trusted-publishing automation.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Tailkitty compared with the existing PyPI project
|
|
2
|
+
|
|
3
|
+
Both projects expose the upstream Tailcat command through Python and use an upstream-compatible
|
|
4
|
+
native data plane. The existing [`pytailcat`](https://pypi.org/project/pytailcat/) primarily ships
|
|
5
|
+
prebuilt executables with a small process wrapper. This implementation adds substantial Python-side
|
|
6
|
+
functionality and a more inspectable supply chain under the distinct Tailkitty name.
|
|
7
|
+
|
|
8
|
+
| Capability | Existing PyPI project | This implementation |
|
|
9
|
+
| --- | --- | --- |
|
|
10
|
+
| Upstream-compatible data plane | Bundled executable | Pinned, verified bundled executable |
|
|
11
|
+
| Token parsing and validation | Delegated to executable | Native Python typed models |
|
|
12
|
+
| DERP resolution and caching | Delegated to executable | Native Python with ETag/stale fallback |
|
|
13
|
+
| DNS `tailcat=` destination lookup | Delegated to executable | Sync and async Python APIs |
|
|
14
|
+
| Process API | Thin synchronous wrapper | Sync/async clients and managed servers |
|
|
15
|
+
| Bundle integrity | Package-manager transport integrity | Runtime manifest, target, size, and SHA-256 checks |
|
|
16
|
+
| Reproducible local toolchain | Not the focus | mise + uv + exact Go compiler and revision |
|
|
17
|
+
| Release evidence | Prebuilt wheels | Matrix verification, checksums, and provenance workflow |
|
|
18
|
+
|
|
19
|
+
The remaining architectural boundary is intentional: reimplementing Tailscale magicsock,
|
|
20
|
+
userspace WireGuard, DERP routing, and gVisor netstack faithfully in pure Python would be a separate
|
|
21
|
+
networking stack and would create interoperability and security risk. The control-plane and wire
|
|
22
|
+
format are Python; the interoperable encrypted transport stays upstream.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# 100-iteration improvement ledger
|
|
2
|
+
|
|
3
|
+
Each checkbox is a distinct implementation, hardening, verification, or documentation pass. Items
|
|
4
|
+
are marked only after their stated evidence exists.
|
|
5
|
+
|
|
6
|
+
## 001-010 — reproducible environment
|
|
7
|
+
|
|
8
|
+
- [x] 001. Update and pin uv to 0.12.7 with mise.
|
|
9
|
+
- [x] 002. Pin Python 3.13.11 with mise.
|
|
10
|
+
- [x] 003. Pin Go 1.26.5 with mise.
|
|
11
|
+
- [x] 004. Keep the virtual environment driven by uv.
|
|
12
|
+
- [x] 005. Lock all Python runtime dependencies.
|
|
13
|
+
- [x] 006. Lock all Python development dependencies.
|
|
14
|
+
- [x] 007. Add a one-command mise setup task.
|
|
15
|
+
- [x] 008. Add a locked CI dependency-sync step.
|
|
16
|
+
- [x] 009. Move package, Tailcat, and Go pins into central constants.
|
|
17
|
+
- [x] 010. Test that project metadata and runtime versions agree.
|
|
18
|
+
|
|
19
|
+
## 011-020 — Python-native control plane
|
|
20
|
+
|
|
21
|
+
- [x] 011. Decode Tailcat CBOR tokens in Python.
|
|
22
|
+
- [x] 012. Model connection data with typed dataclasses.
|
|
23
|
+
- [x] 013. Validate token prefixes and base64 payloads.
|
|
24
|
+
- [x] 014. Validate node-key length and structure.
|
|
25
|
+
- [x] 015. Validate DERP region fields.
|
|
26
|
+
- [x] 016. Re-encode resolved Tailcat tokens in Python.
|
|
27
|
+
- [x] 017. Resolve DERP maps without invoking Go.
|
|
28
|
+
- [x] 018. Cache DERP maps on disk with a bounded lifetime.
|
|
29
|
+
- [x] 019. Revalidate DERP caches with HTTP ETags.
|
|
30
|
+
- [x] 020. Fall back to stale DERP data during network failure.
|
|
31
|
+
|
|
32
|
+
## 021-030 — Python APIs and process safety
|
|
33
|
+
|
|
34
|
+
- [x] 021. Resolve DNS `tailcat=` TXT destinations synchronously.
|
|
35
|
+
- [x] 022. Resolve DNS destinations asynchronously.
|
|
36
|
+
- [x] 023. Add a typed synchronous client.
|
|
37
|
+
- [x] 024. Add an asyncio client.
|
|
38
|
+
- [x] 025. Add a managed synchronous server process.
|
|
39
|
+
- [x] 026. Add a managed asyncio server process.
|
|
40
|
+
- [x] 027. Capture server readiness without blocking stdout.
|
|
41
|
+
- [x] 028. Clean up forgotten child processes at interpreter shutdown.
|
|
42
|
+
- [x] 029. Preserve exit status and stderr for non-raising calls.
|
|
43
|
+
- [x] 030. Translate an empty allow-list to the secure `--allow=none` value.
|
|
44
|
+
|
|
45
|
+
## 031-040 — pinned binary construction
|
|
46
|
+
|
|
47
|
+
- [x] 031. Pin the exact upstream Tailcat pseudo-version.
|
|
48
|
+
- [x] 032. Fetch the command package rather than an ambiguous module root.
|
|
49
|
+
- [x] 033. Build inside an isolated temporary Go module.
|
|
50
|
+
- [x] 034. Disable CGO for portable cross-compilation.
|
|
51
|
+
- [x] 035. Strip source paths with `-trimpath`.
|
|
52
|
+
- [x] 036. Disable VCS stamping.
|
|
53
|
+
- [x] 037. Remove the Go build ID.
|
|
54
|
+
- [x] 038. Strip symbols and debug tables.
|
|
55
|
+
- [x] 039. Set baseline amd64 and arm64 CPU levels.
|
|
56
|
+
- [x] 040. Retry transient module-download failures with a bounded backoff.
|
|
57
|
+
|
|
58
|
+
## 041-050 — target matrix and build safety
|
|
59
|
+
|
|
60
|
+
- [x] 041. Model build targets with immutable typed records.
|
|
61
|
+
- [x] 042. Support macOS arm64.
|
|
62
|
+
- [x] 043. Support macOS x86-64.
|
|
63
|
+
- [x] 044. Support Linux x86-64.
|
|
64
|
+
- [x] 045. Support Linux arm64.
|
|
65
|
+
- [x] 046. Support Windows x86-64.
|
|
66
|
+
- [x] 047. Normalize common machine-architecture aliases.
|
|
67
|
+
- [x] 048. Detect and reject unsupported build hosts.
|
|
68
|
+
- [x] 049. Validate Mach-O, ELF, and PE executable headers.
|
|
69
|
+
- [x] 050. Replace completed binaries atomically and remove stale opposite-OS files.
|
|
70
|
+
|
|
71
|
+
## 051-060 — platform-wheel packaging
|
|
72
|
+
|
|
73
|
+
- [x] 051. Migrate to Hatchling for a programmable wheel hook.
|
|
74
|
+
- [x] 052. Mark binary wheels as non-pure.
|
|
75
|
+
- [x] 053. Emit exact Python/ABI/platform wheel tags.
|
|
76
|
+
- [x] 054. Use a correct macOS 12 deployment floor.
|
|
77
|
+
- [x] 055. Use conservative manylinux 2.17 Linux tags.
|
|
78
|
+
- [x] 056. Force-include only the selected staged executable.
|
|
79
|
+
- [x] 057. Force-include its matching integrity manifest.
|
|
80
|
+
- [x] 058. Reject a caller-supplied tag that disagrees with the bundle.
|
|
81
|
+
- [x] 059. Keep generated binaries out of source distributions.
|
|
82
|
+
- [x] 060. Retain a pure-Python wheel fallback when no bundle is staged.
|
|
83
|
+
|
|
84
|
+
## 061-070 — runtime integrity and discovery
|
|
85
|
+
|
|
86
|
+
- [x] 061. Define a versioned JSON bundle-manifest schema.
|
|
87
|
+
- [x] 062. Record target, platform tag, module, revision, compiler, size, and SHA-256.
|
|
88
|
+
- [x] 063. Reject unsupported manifest schemas.
|
|
89
|
+
- [x] 064. Reject module or upstream-version mismatches.
|
|
90
|
+
- [x] 065. Reject path traversal and symlinked executables.
|
|
91
|
+
- [x] 066. Reject invalid digests and implausible bundle sizes.
|
|
92
|
+
- [x] 067. Recompute size and SHA-256 before execution.
|
|
93
|
+
- [x] 068. Reject a valid bundle copied to an incompatible runtime platform.
|
|
94
|
+
- [x] 069. Restore a missing POSIX user-execute bit after integrity validation.
|
|
95
|
+
- [x] 070. Cache successful verification while preserving explicit cache invalidation for tests.
|
|
96
|
+
|
|
97
|
+
## 071-080 — diagnostics and artifact verification
|
|
98
|
+
|
|
99
|
+
- [x] 071. Give `TAILKITTY_BACKEND` explicit, fail-closed priority.
|
|
100
|
+
- [x] 072. Prefer verified wheel bundles over development and PATH helpers.
|
|
101
|
+
- [x] 073. Preserve a migration fallback for the former `tailcat-go` development filename.
|
|
102
|
+
- [x] 074. Expose backend path, source, version, and manifest metadata.
|
|
103
|
+
- [x] 075. Add human-readable `tailcat doctor` output.
|
|
104
|
+
- [x] 076. Add machine-readable `tailcat doctor --json` output.
|
|
105
|
+
- [x] 077. Reject unsafe or duplicate wheel archive paths.
|
|
106
|
+
- [x] 078. Verify WHEEL purity and compatibility metadata.
|
|
107
|
+
- [x] 079. Verify the embedded executable and manifest together.
|
|
108
|
+
- [x] 080. Verify every wheel `RECORD` digest, size, and member mapping.
|
|
109
|
+
|
|
110
|
+
## 081-090 — automation, metadata, and supply chain
|
|
111
|
+
|
|
112
|
+
- [x] 081. Add unit coverage for bundle corruption and backend precedence.
|
|
113
|
+
- [x] 082. Run Ruff, formatting, strict mypy, and pytest from one mise task.
|
|
114
|
+
- [x] 083. Add a five-target CI wheel matrix.
|
|
115
|
+
- [x] 084. Add isolated host-wheel installation smoke testing in CI.
|
|
116
|
+
- [x] 085. Add binary-free source-distribution CI.
|
|
117
|
+
- [x] 086. Add checksums and GitHub build-provenance attestations.
|
|
118
|
+
- [x] 087. Add OIDC trusted-publishing automation with least-privilege permissions.
|
|
119
|
+
- [x] 088. Pin third-party GitHub Actions to immutable commits.
|
|
120
|
+
- [x] 089. Add PEP 561 typing metadata, classifiers, URLs, and third-party notices.
|
|
121
|
+
- [x] 090. Document building, security, architecture boundaries, and the existing-project comparison.
|
|
122
|
+
|
|
123
|
+
## 091-100 — real artifact and integration validation
|
|
124
|
+
|
|
125
|
+
- [x] 091. Cross-compile and structurally verify all five real platform wheels locally.
|
|
126
|
+
- [x] 092. Install the host wheel into an isolated environment and discover its verified bundle.
|
|
127
|
+
- [x] 093. Rebuild identical host binaries and prove byte-for-byte reproducibility.
|
|
128
|
+
- [x] 094. Detect and close Go's silent automatic-toolchain substitution path.
|
|
129
|
+
- [x] 095. Build and inspect the no-bundle pure-Python wheel fallback.
|
|
130
|
+
- [x] 096. Build and inspect the binary-free source distribution.
|
|
131
|
+
- [x] 097. Run the full suite on the minimum supported Python 3.11.
|
|
132
|
+
- [x] 098. Repeat live encrypted transfer testing and capture the current external DERP timeout
|
|
133
|
+
after earlier successful bundled transfers.
|
|
134
|
+
- [x] 099. Rebuild final artifacts and pass the complete lint, type, test, and integrity audit.
|
|
135
|
+
- [x] 100. Audit this ledger against the workspace and deliver the handoff.
|
tailkitty-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, Tailkitty contributors
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice,
|
|
9
|
+
this list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|