wraith-cli 1.1.0__tar.gz → 1.3.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.
- wraith_cli-1.3.0/.env.example +13 -0
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/.gitea/workflows/pages.yml +1 -0
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/.gitea/workflows/test.yml +15 -4
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/.gitignore +1 -0
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/.pre-commit-config.yaml +16 -0
- wraith_cli-1.3.0/.secrets.baseline +131 -0
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/CHANGELOG.md +4 -0
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/PKG-INFO +65 -38
- wraith_cli-1.3.0/README.md +98 -0
- wraith_cli-1.3.0/docs/architecture.md +86 -0
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/docs/index.md +1 -1
- wraith_cli-1.3.0/docs/reference.md +62 -0
- wraith_cli-1.3.0/docs/security.md +42 -0
- wraith_cli-1.3.0/docs/usage.md +80 -0
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/mkdocs.yml +2 -0
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/pyproject.toml +7 -3
- wraith_cli-1.3.0/src/wraith_cli/main.py +339 -0
- wraith_cli-1.3.0/src/wraith_cli/qol.py +47 -0
- wraith_cli-1.3.0/src/wraith_cli/repo_make.py +88 -0
- wraith_cli-1.3.0/src/wraith_cli/shield.py +187 -0
- wraith_cli-1.3.0/tests/test_cli.py +301 -0
- wraith_cli-1.3.0/tests/test_qol.py +58 -0
- wraith_cli-1.3.0/tests/test_repo_make.py +115 -0
- wraith_cli-1.3.0/tests/test_shield.py +236 -0
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/uv.lock +56 -1
- wraith_cli-1.1.0/.env.example +0 -17
- wraith_cli-1.1.0/README.md +0 -74
- wraith_cli-1.1.0/docs/reference.md +0 -18
- wraith_cli-1.1.0/docs/usage.md +0 -26
- wraith_cli-1.1.0/src/wraith_cli/main.py +0 -89
- wraith_cli-1.1.0/tests/test_cli.py +0 -97
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/.cz.yaml +0 -0
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/.gitea/CODEOWNERS.md +0 -0
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/.gitea/PULL_REQUEST_TEMPLATE.md +0 -0
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/.gitea/workflows/release.yml +0 -0
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/CONTRIBUTING.md +0 -0
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/LICENSE +0 -0
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/bin/build.sh +0 -0
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/bin/run_tests.sh +0 -0
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/bin/setup_venv.sh +0 -0
- {wraith_cli-1.1.0 → wraith_cli-1.3.0}/src/wraith_cli/__init__.py +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Environment Variables Example file
|
|
2
|
+
VIKING_TOKEN=your_token_here
|
|
3
|
+
VIKING_ACCOUNT=default
|
|
4
|
+
VIKING_USER=admin
|
|
5
|
+
|
|
6
|
+
WRAITH_COMPOSE_PATH=/home/user/example/docker
|
|
7
|
+
|
|
8
|
+
GITEA_COMPOSE_PATH=/home/user/example/gitea
|
|
9
|
+
GITEA_API_URL="http://your-gitea-instance:3000"
|
|
10
|
+
GITEA_TOKEN="your_personal_access_token"
|
|
11
|
+
GITEA_TEMPLATE_URL="https://gitea.domain.com/user/repo-template.git"
|
|
12
|
+
|
|
13
|
+
SCRUTINY_URL=http://127.0.0.1:8090
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
name:
|
|
1
|
+
name: Wraith-CLI CI
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
@@ -9,18 +9,29 @@ jobs:
|
|
|
9
9
|
test-and-verify:
|
|
10
10
|
runs-on: ghost-runner
|
|
11
11
|
steps:
|
|
12
|
+
|
|
12
13
|
- name: Check out code
|
|
13
14
|
uses: actions/checkout@v4
|
|
14
15
|
with:
|
|
15
16
|
fetch-depth: 0
|
|
17
|
+
|
|
18
|
+
- name: Install Wraith-CLI
|
|
19
|
+
run: |
|
|
20
|
+
uv pip install --system --break-system-packages -e .
|
|
21
|
+
|
|
16
22
|
- name: Run Production Tests
|
|
17
23
|
run: |
|
|
18
24
|
chmod +x bin/run_tests.sh
|
|
19
25
|
./bin/run_tests.sh --no-venv
|
|
20
26
|
env:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
27
|
+
VIKING_TOKEN: "your_token_here"
|
|
28
|
+
VIKING_ACCOUNT: "default"
|
|
29
|
+
VIKING_USER: "admin"
|
|
30
|
+
WRAITH_COMPOSE_PATH: "/home/user/example/docker"
|
|
31
|
+
GITEA_COMPOSE_PATH: "/home/user/example/gitea"
|
|
32
|
+
GITEA_API_URL: "http://your-gitea-instance:3000"
|
|
33
|
+
GITEA_TOKEN: "your_personal_access_token"
|
|
34
|
+
GITEA_TEMPLATE_URL: "https://gitea.domain.com/user/repo-template.git"
|
|
24
35
|
PYTHONPATH: .
|
|
25
36
|
|
|
26
37
|
auto-merge:
|
|
@@ -14,6 +14,22 @@ repos:
|
|
|
14
14
|
args: ["--fix"]
|
|
15
15
|
- id: ruff-format
|
|
16
16
|
|
|
17
|
+
- repo: local
|
|
18
|
+
hooks:
|
|
19
|
+
- id: ty
|
|
20
|
+
name: ty
|
|
21
|
+
entry: uv run ty check
|
|
22
|
+
language: system
|
|
23
|
+
types: [python]
|
|
24
|
+
pass_filenames: false
|
|
25
|
+
|
|
26
|
+
- repo: https://github.com/Yelp/detect-secrets
|
|
27
|
+
rev: v1.5.0
|
|
28
|
+
hooks:
|
|
29
|
+
- id: detect-secrets
|
|
30
|
+
args: ['--baseline', '.secrets.baseline']
|
|
31
|
+
exclude: package-lock.json
|
|
32
|
+
|
|
17
33
|
- repo: local
|
|
18
34
|
hooks:
|
|
19
35
|
- id: pytest-coverage
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.5.0",
|
|
3
|
+
"plugins_used": [
|
|
4
|
+
{
|
|
5
|
+
"name": "ArtifactoryDetector"
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"name": "AWSKeyDetector"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"name": "AzureStorageKeyDetector"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "Base64HighEntropyString",
|
|
15
|
+
"limit": 4.5
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "BasicAuthDetector"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "CloudantDetector"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "DiscordBotTokenDetector"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "GitHubTokenDetector"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "GitLabTokenDetector"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "HexHighEntropyString",
|
|
34
|
+
"limit": 3.0
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "IbmCloudIamDetector"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "IbmCosHmacDetector"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "IPPublicDetector"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"name": "JwtTokenDetector"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"name": "KeywordDetector",
|
|
50
|
+
"keyword_exclude": ""
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"name": "MailchimpDetector"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "NpmDetector"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "OpenAIDetector"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"name": "PrivateKeyDetector"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "PypiTokenDetector"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "SendGridDetector"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "SlackDetector"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"name": "SoftlayerDetector"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"name": "SquareOAuthDetector"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "StripeDetector"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"name": "TelegramBotTokenDetector"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"name": "TwilioKeyDetector"
|
|
87
|
+
}
|
|
88
|
+
],
|
|
89
|
+
"filters_used": [
|
|
90
|
+
{
|
|
91
|
+
"path": "detect_secrets.filters.allowlist.is_line_allowlisted"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"path": "detect_secrets.filters.common.is_baseline_file",
|
|
95
|
+
"filename": ".secrets.baseline"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
|
|
99
|
+
"min_level": 2
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"path": "detect_secrets.filters.heuristic.is_indirect_reference"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"path": "detect_secrets.filters.heuristic.is_likely_id_string"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"path": "detect_secrets.filters.heuristic.is_lock_file"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"path": "detect_secrets.filters.heuristic.is_potential_uuid"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"path": "detect_secrets.filters.heuristic.is_sequential_string"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"path": "detect_secrets.filters.heuristic.is_swagger_file"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"path": "detect_secrets.filters.heuristic.is_templated_secret"
|
|
127
|
+
}
|
|
128
|
+
],
|
|
129
|
+
"results": {},
|
|
130
|
+
"generated_at": "2026-04-02T05:45:06Z"
|
|
131
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wraith-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Sovereign Command Centre for a Ghost Stack
|
|
5
5
|
Project-URL: Homepage, https://git.thomaspeoples.com/thomaspeoples/wraith-cli
|
|
6
6
|
Project-URL: Documentation, https://www.thomaspeoples.com/gitea-repos/wraith-cli/
|
|
@@ -38,6 +38,7 @@ Requires-Dist: rich>=13.0.0
|
|
|
38
38
|
Requires-Dist: typer>=0.9.0
|
|
39
39
|
Provides-Extra: dev
|
|
40
40
|
Requires-Dist: commitizen; extra == 'dev'
|
|
41
|
+
Requires-Dist: detect-secrets; extra == 'dev'
|
|
41
42
|
Requires-Dist: genbadge[coverage]>=1.1.1; extra == 'dev'
|
|
42
43
|
Requires-Dist: mkdocs-material<=10.0; extra == 'dev'
|
|
43
44
|
Requires-Dist: mkdocs<=2.0; extra == 'dev'
|
|
@@ -46,79 +47,105 @@ Requires-Dist: pymdown-extensions>=10.7.0; extra == 'dev'
|
|
|
46
47
|
Requires-Dist: pytest; extra == 'dev'
|
|
47
48
|
Requires-Dist: pytest-cov; extra == 'dev'
|
|
48
49
|
Requires-Dist: ruff; extra == 'dev'
|
|
50
|
+
Requires-Dist: ty; extra == 'dev'
|
|
51
|
+
Requires-Dist: types-requests; extra == 'dev'
|
|
49
52
|
Description-Content-Type: text/markdown
|
|
50
53
|
|
|
51
54
|
[](https://www.thomaspeoples.com/gitea-repos/wraith-cli/)
|
|
52
|
-

|
|
56
|
+

|
|
57
|
+

|
|
55
58
|
|
|
56
59
|
|
|
57
60
|
# 👻 Wraith-CLI
|
|
58
61
|
### *Sovereign Orchestration for the Ghost Stack*
|
|
59
62
|
|
|
60
|
-
**Wraith-CLI** is the nervous system of the Ghost Stack. It bridges the gap between
|
|
63
|
+
**Wraith-CLI** is the nervous system of the Ghost Stack. It bridges the gap between
|
|
64
|
+
high-level container orchestration and bare-metal reality, providing the "Ghost Factory"
|
|
65
|
+
for instant project scaffolding.
|
|
61
66
|
|
|
62
67
|
---
|
|
63
68
|
|
|
64
|
-
##
|
|
69
|
+
## 🏗️ The Ghost Factory (New)
|
|
65
70
|
|
|
66
|
-
**
|
|
71
|
+
The `spawn` command allows you to go from **Idea to Code** in under 5 seconds by
|
|
72
|
+
bleaching a template and provisioning a private Gitea repository automatically.
|
|
67
73
|
|
|
68
74
|
```bash
|
|
69
|
-
|
|
70
|
-
uv tool install wraith-cli
|
|
71
|
-
|
|
72
|
-
# Standard pip
|
|
73
|
-
pip install wraith-cli
|
|
75
|
+
wraith spawn my-new-api
|
|
74
76
|
```
|
|
75
77
|
|
|
76
|
-
|
|
78
|
+
1. **🧬 Clones** your `GHOST_TEMPLATE_URL`.
|
|
79
|
+
2. **🧹 Bleaches** all previous git history.
|
|
80
|
+
3. **🌐 Provisions** a new private repo via the Gitea API.
|
|
81
|
+
4. **🚀 Pushes** the clean stack to your Sovereign remote.
|
|
77
82
|
|
|
78
83
|
---
|
|
79
84
|
|
|
80
85
|
## 🛠️ Operational Manual
|
|
81
86
|
|
|
82
|
-
| Command |
|
|
83
|
-
|
|
84
|
-
| wraith
|
|
85
|
-
| wraith
|
|
86
|
-
| wraith
|
|
87
|
-
| wraith
|
|
87
|
+
| Command | Feature | Status |
|
|
88
|
+
|--------------------------|------------------------|---------------------------------------------|
|
|
89
|
+
| `wraith spawn <name>` | **The Ghost Factory** | 🏗️ Scaffolds new repos via Gitea API. |
|
|
90
|
+
| `wraith update` | **Global Update** | 🟢 PyPI-linked & `uv` powered. |
|
|
91
|
+
| `wraith ps` | **Rich Observability** | 🟢 Sovereign Dark styling for Docker. |
|
|
92
|
+
| `wraith tail <svc>` | **Flexible Logging** | 🟢 Supports `--path` & Env Vars. |
|
|
93
|
+
| `wraith status` | **Heartbeat** | 🟢 Monitor OpenViking (Port 1933). |
|
|
94
|
+
| `wraith runner-reset` | **Runner Defence** | 🟢 CI/CD maintenance & registration wipe. |
|
|
95
|
+
| `wraith --version` | **Self-Identity** | 🟢 Eager callback for versioning. |
|
|
88
96
|
|
|
89
97
|
---
|
|
90
98
|
|
|
91
|
-
##
|
|
99
|
+
## 🚀 Installation & Updates
|
|
92
100
|
|
|
93
|
-
|
|
101
|
+
**Wraith-CLI** is managed via `uv` for hermetic stability.
|
|
94
102
|
|
|
95
103
|
```bash
|
|
96
|
-
|
|
97
|
-
uv
|
|
98
|
-
uv run pre-commit install
|
|
99
|
-
|
|
100
|
-
### 2. The Quality Gate
|
|
101
|
-
uv run pytest
|
|
104
|
+
# Initial Installation
|
|
105
|
+
uv tool install wraith-cli
|
|
102
106
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
./bin/build.sh
|
|
107
|
+
# Sovereign Update
|
|
108
|
+
wraith update
|
|
106
109
|
```
|
|
107
110
|
|
|
108
111
|
---
|
|
109
112
|
|
|
110
113
|
## 🔐 Environment Configuration
|
|
111
114
|
|
|
112
|
-
Defined in
|
|
115
|
+
Defined in your `.env` or system environment. **HTTPS is required** for automated
|
|
116
|
+
Gitea provisioning.
|
|
113
117
|
|
|
114
|
-
| Variable
|
|
115
|
-
|
|
116
|
-
|
|
|
117
|
-
|
|
|
118
|
+
| Variable | Purpose | Required For |
|
|
119
|
+
|------------------------|--------------------------------------------------|-----------------|
|
|
120
|
+
| `GITEA_API_URL` | Base URL (e.g., `https://git.domain.com`) | `spawn` |
|
|
121
|
+
| `GITEA_TOKEN` | Personal Access Token (PAT) | `spawn` |
|
|
122
|
+
| `GITEA_TEMPLATE_URL` | HTTPS URL of your base `ghost-template` | `spawn` |
|
|
123
|
+
| `GITEA_COMPOSE_PATH` | Path to Gitea Docker directory | `runner-reset` |
|
|
124
|
+
| `VIKING_BASE_URL` | API endpoint for heartbeat checks | `status` |
|
|
125
|
+
| `WRAITH_COMPOSE_PATH` | Default path for stack logs/ps | `tail`, `ps` |
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 🧪 Developer Quality Gate
|
|
130
|
+
|
|
131
|
+
We use `uv` for hermetic environment management and maintain a strict **>80% coverage**
|
|
132
|
+
requirement.
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# Initialise the Environment
|
|
136
|
+
uv sync --all-extras
|
|
137
|
+
uv run pre-commit install
|
|
138
|
+
|
|
139
|
+
# The Quality Gate
|
|
140
|
+
uv run pytest --cov=src
|
|
141
|
+
```
|
|
118
142
|
|
|
119
143
|
---
|
|
120
144
|
|
|
121
145
|
## 📜 Sovereign Principles
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
146
|
+
|
|
147
|
+
1. **Distributed Sovereignty:** Available on PyPI for the world, but optimised for
|
|
148
|
+
local-first, private-registry mirrors.
|
|
149
|
+
2. **Atomic Execution:** Use `uv run` to ensure consistency across the stack.
|
|
150
|
+
3. **Hardware First:** Prioritise bare-metal health and container stability over
|
|
151
|
+
abstraction.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
[](https://www.thomaspeoples.com/gitea-repos/wraith-cli/)
|
|
2
|
+

|
|
3
|
+

|
|
4
|
+

|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# 👻 Wraith-CLI
|
|
8
|
+
### *Sovereign Orchestration for the Ghost Stack*
|
|
9
|
+
|
|
10
|
+
**Wraith-CLI** is the nervous system of the Ghost Stack. It bridges the gap between
|
|
11
|
+
high-level container orchestration and bare-metal reality, providing the "Ghost Factory"
|
|
12
|
+
for instant project scaffolding.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 🏗️ The Ghost Factory (New)
|
|
17
|
+
|
|
18
|
+
The `spawn` command allows you to go from **Idea to Code** in under 5 seconds by
|
|
19
|
+
bleaching a template and provisioning a private Gitea repository automatically.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
wraith spawn my-new-api
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
1. **🧬 Clones** your `GHOST_TEMPLATE_URL`.
|
|
26
|
+
2. **🧹 Bleaches** all previous git history.
|
|
27
|
+
3. **🌐 Provisions** a new private repo via the Gitea API.
|
|
28
|
+
4. **🚀 Pushes** the clean stack to your Sovereign remote.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 🛠️ Operational Manual
|
|
33
|
+
|
|
34
|
+
| Command | Feature | Status |
|
|
35
|
+
|--------------------------|------------------------|---------------------------------------------|
|
|
36
|
+
| `wraith spawn <name>` | **The Ghost Factory** | 🏗️ Scaffolds new repos via Gitea API. |
|
|
37
|
+
| `wraith update` | **Global Update** | 🟢 PyPI-linked & `uv` powered. |
|
|
38
|
+
| `wraith ps` | **Rich Observability** | 🟢 Sovereign Dark styling for Docker. |
|
|
39
|
+
| `wraith tail <svc>` | **Flexible Logging** | 🟢 Supports `--path` & Env Vars. |
|
|
40
|
+
| `wraith status` | **Heartbeat** | 🟢 Monitor OpenViking (Port 1933). |
|
|
41
|
+
| `wraith runner-reset` | **Runner Defence** | 🟢 CI/CD maintenance & registration wipe. |
|
|
42
|
+
| `wraith --version` | **Self-Identity** | 🟢 Eager callback for versioning. |
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 🚀 Installation & Updates
|
|
47
|
+
|
|
48
|
+
**Wraith-CLI** is managed via `uv` for hermetic stability.
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Initial Installation
|
|
52
|
+
uv tool install wraith-cli
|
|
53
|
+
|
|
54
|
+
# Sovereign Update
|
|
55
|
+
wraith update
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 🔐 Environment Configuration
|
|
61
|
+
|
|
62
|
+
Defined in your `.env` or system environment. **HTTPS is required** for automated
|
|
63
|
+
Gitea provisioning.
|
|
64
|
+
|
|
65
|
+
| Variable | Purpose | Required For |
|
|
66
|
+
|------------------------|--------------------------------------------------|-----------------|
|
|
67
|
+
| `GITEA_API_URL` | Base URL (e.g., `https://git.domain.com`) | `spawn` |
|
|
68
|
+
| `GITEA_TOKEN` | Personal Access Token (PAT) | `spawn` |
|
|
69
|
+
| `GITEA_TEMPLATE_URL` | HTTPS URL of your base `ghost-template` | `spawn` |
|
|
70
|
+
| `GITEA_COMPOSE_PATH` | Path to Gitea Docker directory | `runner-reset` |
|
|
71
|
+
| `VIKING_BASE_URL` | API endpoint for heartbeat checks | `status` |
|
|
72
|
+
| `WRAITH_COMPOSE_PATH` | Default path for stack logs/ps | `tail`, `ps` |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 🧪 Developer Quality Gate
|
|
77
|
+
|
|
78
|
+
We use `uv` for hermetic environment management and maintain a strict **>80% coverage**
|
|
79
|
+
requirement.
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Initialise the Environment
|
|
83
|
+
uv sync --all-extras
|
|
84
|
+
uv run pre-commit install
|
|
85
|
+
|
|
86
|
+
# The Quality Gate
|
|
87
|
+
uv run pytest --cov=src
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 📜 Sovereign Principles
|
|
93
|
+
|
|
94
|
+
1. **Distributed Sovereignty:** Available on PyPI for the world, but optimised for
|
|
95
|
+
local-first, private-registry mirrors.
|
|
96
|
+
2. **Atomic Execution:** Use `uv run` to ensure consistency across the stack.
|
|
97
|
+
3. **Hardware First:** Prioritise bare-metal health and container stability over
|
|
98
|
+
abstraction.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# 🏛️ Architecture & Decision Records
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## 1. High-Level Design
|
|
6
|
+
|
|
7
|
+
Wraith follows a **Functional Core, Imperative Shell** pattern.
|
|
8
|
+
|
|
9
|
+
- **The Shell (`main.py`):** Handles the "dirty" work of CLI parsing, environment
|
|
10
|
+
loading, and printing to `stdout`.
|
|
11
|
+
- **The Core (`repo_make.py`, `qol.py`):** Pure logic functions that perform the actual
|
|
12
|
+
heavy lifting — API calls, Git operations, Docker formatting.
|
|
13
|
+
|
|
14
|
+
This separation ensures the core remains independently testable without invoking the
|
|
15
|
+
CLI layer, and that the shell stays thin enough to reason about at a glance.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 2. ADR 001 — Tooling Selection
|
|
20
|
+
|
|
21
|
+
> **Status:** Accepted. These dependencies are intentional and should not be replaced
|
|
22
|
+
> without a corresponding ADR entry.
|
|
23
|
+
|
|
24
|
+
| Decision | Choice | Rationale |
|
|
25
|
+
|--------------------|-----------|------------------------------------------------------------------------------------------------|
|
|
26
|
+
| **CLI Framework** | `typer` | Native type-hint support. Built on Click but with significantly less boilerplate. |
|
|
27
|
+
| **Package Manager**| `uv` | Rust-based, hermetic, and fast. Replaces `pip`, `poetry`, and `venv` with a single binary. |
|
|
28
|
+
| **Terminal Output**| `rich` | First-class Markdown and table rendering. Essential for the Sovereign Dark aesthetic. |
|
|
29
|
+
| **Testing** | `pytest` | Industry standard. Excellent `subprocess` mocking support for hermetic offline tests. |
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 3. ADR 002 — Sovereign Security & Authentication
|
|
34
|
+
|
|
35
|
+
> **Status:** Accepted. Do not introduce persistent credential storage without
|
|
36
|
+
> revisiting this decision.
|
|
37
|
+
|
|
38
|
+
**Decision:** Environment-only credential configuration via `.env` or shell exports.
|
|
39
|
+
|
|
40
|
+
**Rejected alternative:** Storing Gitea credentials in a local SQLite database or
|
|
41
|
+
config file (e.g., `~/.wraith/config`).
|
|
42
|
+
|
|
43
|
+
**Rationale:** Keeps Wraith stateless between sessions. If a machine is compromised,
|
|
44
|
+
credentials are not sitting in a plaintext config file — they vanish when the shell
|
|
45
|
+
session ends. The attack surface is the user's environment, not Wraith's own storage.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 4. The Quality Gate
|
|
50
|
+
|
|
51
|
+
We treat **type hints** as a functional requirement, not a suggestion. Because `typer`
|
|
52
|
+
relies on Python 3.12+ annotations to construct its CLI interface, a type error is a
|
|
53
|
+
runtime bug — not a style violation.
|
|
54
|
+
|
|
55
|
+
### Static Analysis — Ruff
|
|
56
|
+
|
|
57
|
+
All code is linted and formatted via `ruff` in opinionated mode, enforced at commit
|
|
58
|
+
time via `pre-commit`. This covers style, import ordering, and security anti-patterns
|
|
59
|
+
in a single pass.
|
|
60
|
+
|
|
61
|
+
### Type Integrity
|
|
62
|
+
|
|
63
|
+
Type annotations are enforced strictly. Functions accepting a `Path` must not receive
|
|
64
|
+
a `str`; optional environment variables must be handled as `Optional[str]`, not assumed
|
|
65
|
+
present.
|
|
66
|
+
|
|
67
|
+
### Test Coverage — pytest
|
|
68
|
+
|
|
69
|
+
We maintain a strict **>80% coverage gate**, with all network and `subprocess` calls
|
|
70
|
+
mocked for offline, hermetic execution.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# The Lead Engineer's Pre-Flight Check
|
|
74
|
+
uv run ruff check . # Linting & security anti-patterns
|
|
75
|
+
uv run ruff format . # Consistency
|
|
76
|
+
uv run pytest --cov=src # Logical integrity & coverage gate
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 5. Future Roadmap
|
|
82
|
+
|
|
83
|
+
| Path | Codename | Description |
|
|
84
|
+
|------|---------------------|-----------------------------------------------------------------------------|
|
|
85
|
+
| 3 | **Ghost Watcher** | Background daemon to monitor stack health via `status` and auto-restart failed runners. |
|
|
86
|
+
| 4 | **Sovereign UI** | `textual`-based TUI for real-time stack dashboarding. |
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# 🔩 Technical Reference
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## 🏗️ Architecture
|
|
6
|
+
|
|
7
|
+
**Wraith** is engineered on **Python 3.12+**. Like its namesake, it is designed for silent, effortless power. It leverages a modern Sovereign stack:
|
|
8
|
+
|
|
9
|
+
| Concern | Library | Role |
|
|
10
|
+
|--------------------|--------------|-------------------------------------------------------|
|
|
11
|
+
| **Orchestration** | `typer` | CLI interface and command routing. |
|
|
12
|
+
| **Visuals** | `rich` | High-contrast terminal rendering and Markdown support.|
|
|
13
|
+
| **Package Mgmt** | `uv` | Lightning-fast, hermetic dependency locking. |
|
|
14
|
+
| **Networking** | `requests` | Gitea API interactions. |
|
|
15
|
+
| **System** | `subprocess` | Low-level Docker and Git execution. |
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 🧬 Modular Logic
|
|
20
|
+
|
|
21
|
+
The codebase is partitioned to ensure high testability and separation of concerns:
|
|
22
|
+
|
|
23
|
+
| Module | Responsibility |
|
|
24
|
+
|---------------|-------------------------------------------------------------------------|
|
|
25
|
+
| `main.py` | **The Switchboard.** CLI routing, UI splash, and env var loading. |
|
|
26
|
+
| `repo_make.py`| **The Factory.** Gitea API calls and Git "Bleach & Push" logic. |
|
|
27
|
+
| `qol.py` | **Quality of Life.** Docker table formatting and version checks. |
|
|
28
|
+
|
|
29
|
+
### 🔐 Authentication Logic
|
|
30
|
+
|
|
31
|
+
Wraith uses **HTTPS Token Injection** to bypass interactive password prompts. When a command requires Gitea access, the logic identifies the protocol and injects credentials as follows:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
https://oauth2:{GITEA_TOKEN}@git.domain.com/repo.git
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 🚨 Error Codes & Troubleshooting
|
|
40
|
+
|
|
41
|
+
| Code | Meaning | Resolution |
|
|
42
|
+
|----------|--------------------------|----------------------------------------------------------------|
|
|
43
|
+
| `0` | Success | Command executed perfectly. |
|
|
44
|
+
| `1` | Configuration Error | Missing `.env` variables or 404 API endpoint. |
|
|
45
|
+
| `128` | Git / Auth Error | Token invalid, or repository already exists on remote. |
|
|
46
|
+
| `Abort` | User Cancelled | Triggered during `runner-reset` if requirements aren't met. |
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 🧪 Test Suite & Quality Gate
|
|
51
|
+
|
|
52
|
+
We maintain a strict **Sovereign Quality Gate**. No code enters the main branch without passing the full suite.
|
|
53
|
+
|
|
54
|
+
- **Coverage Target:** >80%, strictly enforced via `pytest-cov`.
|
|
55
|
+
- **Engine:** `pytest` + `coverage.py`.
|
|
56
|
+
- **Mocking:** All network and `subprocess` calls must be mocked under `tests/` to
|
|
57
|
+
permit offline, hermetic testing.
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Run the Gate locally
|
|
61
|
+
uv run pytest --cov=src --cov-report=term-missing
|
|
62
|
+
```
|