wraith-cli 1.1.0__tar.gz → 1.2.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.
Files changed (38) hide show
  1. wraith_cli-1.2.0/.env.example +11 -0
  2. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/.gitea/workflows/test.yml +15 -4
  3. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/.pre-commit-config.yaml +13 -0
  4. wraith_cli-1.2.0/.secrets.baseline +131 -0
  5. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/CHANGELOG.md +2 -0
  6. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/PKG-INFO +62 -35
  7. wraith_cli-1.2.0/README.md +98 -0
  8. wraith_cli-1.2.0/docs/architecture.md +86 -0
  9. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/docs/index.md +1 -1
  10. wraith_cli-1.2.0/docs/reference.md +62 -0
  11. wraith_cli-1.2.0/docs/security.md +42 -0
  12. wraith_cli-1.2.0/docs/usage.md +80 -0
  13. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/pyproject.toml +17 -1
  14. wraith_cli-1.2.0/src/wraith_cli/main.py +304 -0
  15. wraith_cli-1.2.0/src/wraith_cli/qol.py +47 -0
  16. wraith_cli-1.2.0/src/wraith_cli/repo_make.py +88 -0
  17. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/tests/test_cli.py +51 -5
  18. wraith_cli-1.2.0/tests/test_qol.py +57 -0
  19. wraith_cli-1.2.0/tests/test_repo_make.py +82 -0
  20. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/uv.lock +153 -1
  21. wraith_cli-1.1.0/.env.example +0 -17
  22. wraith_cli-1.1.0/README.md +0 -74
  23. wraith_cli-1.1.0/docs/reference.md +0 -18
  24. wraith_cli-1.1.0/docs/usage.md +0 -26
  25. wraith_cli-1.1.0/src/wraith_cli/main.py +0 -89
  26. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/.cz.yaml +0 -0
  27. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/.gitea/CODEOWNERS.md +0 -0
  28. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/.gitea/PULL_REQUEST_TEMPLATE.md +0 -0
  29. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/.gitea/workflows/pages.yml +0 -0
  30. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/.gitea/workflows/release.yml +0 -0
  31. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/.gitignore +0 -0
  32. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/CONTRIBUTING.md +0 -0
  33. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/LICENSE +0 -0
  34. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/bin/build.sh +0 -0
  35. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/bin/run_tests.sh +0 -0
  36. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/bin/setup_venv.sh +0 -0
  37. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/mkdocs.yml +0 -0
  38. {wraith_cli-1.1.0 → wraith_cli-1.2.0}/src/wraith_cli/__init__.py +0 -0
@@ -0,0 +1,11 @@
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"
@@ -1,4 +1,4 @@
1
- name: Discourse-Bot CI
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
- SOVEREIGN_FORUM_URL: "https://mock.forum"
22
- SOVEREIGN_API_KEY: "mock_key"
23
- SOVEREIGN_USERNAME: "mock_user"
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,19 @@ repos:
14
14
  args: ["--fix"]
15
15
  - id: ruff-format
16
16
 
17
+ - repo: https://github.com/pre-commit/mirrors-mypy
18
+ rev: v1.15.0
19
+ hooks:
20
+ - id: mypy
21
+ additional_dependencies: ['types-requests']
22
+
23
+ - repo: https://github.com/Yelp/detect-secrets
24
+ rev: v1.5.0
25
+ hooks:
26
+ - id: detect-secrets
27
+ args: ['--baseline', '.secrets.baseline']
28
+ exclude: package-lock.json
29
+
17
30
  - repo: local
18
31
  hooks:
19
32
  - 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,3 +1,5 @@
1
+ ## v1.2.0 (2026-04-02)
2
+
1
3
  ## v1.1.0 (2026-03-31)
2
4
 
3
5
  ## v0.15.0 (2026-03-31)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wraith-cli
3
- Version: 1.1.0
3
+ Version: 1.2.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,14 +38,17 @@ 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'
45
+ Requires-Dist: mypy; extra == 'dev'
44
46
  Requires-Dist: pre-commit; extra == 'dev'
45
47
  Requires-Dist: pymdown-extensions>=10.7.0; extra == 'dev'
46
48
  Requires-Dist: pytest; extra == 'dev'
47
49
  Requires-Dist: pytest-cov; extra == 'dev'
48
50
  Requires-Dist: ruff; extra == 'dev'
51
+ Requires-Dist: types-requests; extra == 'dev'
49
52
  Description-Content-Type: text/markdown
50
53
 
51
54
  [![Documentation](https://img.shields.io/badge/docs-live-brightgreen)](https://www.thomaspeoples.com/gitea-repos/wraith-cli/)
@@ -57,68 +60,92 @@ Description-Content-Type: text/markdown
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 high-level containers and bare-metal reality.
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
- ## 🚀 Installation
69
+ ## 🏗️ The Ghost Factory (New)
65
70
 
66
- **Wraith-CLI** can be installed via `uv` (recommended) or `pip`:
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
- # Recommended for CLI tools
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
- > **Note:** Ensure ~/.local/bin is in your $PATH.
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 | Description |
83
- | :--- | :--- |
84
- | wraith ps | Shows all Docker processes in a neat table |
85
- | wraith status | Heartbeat check for OpenViking (Port 1933). |
86
- | wraith runner-reset | Wipes and re-registers the Gitea Action Runner. |
87
- | wraith --help | View the full manifest of available commands. |
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
- ## 🏗️ Developer Workspace
99
+ ## 🚀 Installation & Updates
92
100
 
93
- We use uv for hermetic environment management.
101
+ **Wraith-CLI** is managed via `uv` for hermetic stability.
94
102
 
95
103
  ```bash
96
- ### 1. Initialise the Environment
97
- uv sync --all-extras
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
- ### 3. Sovereign Deployment
104
- chmod +x bin/build.sh
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 `~/.bashrc` or `.env.private`:
115
+ Defined in your `.env` or system environment. **HTTPS is required** for automated
116
+ Gitea provisioning.
113
117
 
114
- | Variable | Purpose | Default |
115
- | :--- | :--- | :--- |
116
- | VIKING_BASE_URL | The API endpoint for the heartbeat check. | http://127.0.0.1:1933/api/v1 |
117
- | GITEA_COMPOSE_PATH | Path to your Gitea Docker Compose directory. | Required for runner-reset |
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
- 1. **Distributed Sovereignty:** Available on PyPI for the world, but optimised for local-first, private-registry mirrors
123
- 2. **Atomic Execution:** Use uv run to ensure consistency.
124
- 3. **Hardware First:** Prioritise bare-metal health and container stability.
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
+ [![Documentation](https://img.shields.io/badge/docs-live-brightgreen)](https://www.thomaspeoples.com/gitea-repos/wraith-cli/)
2
+ ![PyPI - Version](https://img.shields.io/pypi/v/wraith_cli)
3
+ ![PyPI - License](https://img.shields.io/pypi/l/wraith_cli)
4
+ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/wraith_cli)
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. |
@@ -1,7 +1,7 @@
1
1
  # Wraith CLI
2
2
 
3
3
  ![Coverage](coverage.svg)
4
- ![Version](https://img.shields.io/badge/version-1.0.1-blue)
4
+ ![PyPI - Version](https://img.shields.io/pypi/v/wraith_cli)
5
5
 
6
6
  ---
7
7
 
@@ -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
+ ```
@@ -0,0 +1,42 @@
1
+ # 🛡️ Security Policy
2
+
3
+ ---
4
+
5
+ ## 1. The Sovereign Security Model
6
+
7
+ **Wraith** operates as the nervous system of your stack. Because it handles Personal Access Tokens (PATs) and interacts with Docker sockets, it must be treated as a **High-Privilege Utility**.
8
+
9
+ > ⚠️ **This software is provided as-is, without warranty of any kind.** Use in production environments is at your own risk. No support, patches, or security updates are guaranteed.
10
+
11
+ ### 🔐 Credential Handling
12
+
13
+ - **No Persistence:** Wraith does *not* store tokens in its own configuration database. It reads them from the environment (`.env` or shell exports) at runtime.
14
+ - **Memory Safety:** Tokens are used to construct authenticated URLs for Git subprocesses and are not logged to `stdout` or `stderr`.
15
+ - **HTTPS Enforcement:** All Ghost Factory operations require `https://` to ensure tokens are encrypted in transit.
16
+
17
+ > ⚠️ **Be aware:** On shared hardware, `git clone` URLs containing injected tokens can briefly appear in the system process list (e.g., `ps aux`). See [§3 Hardening](#3-hardening-your-installation) for mitigation.
18
+
19
+ ---
20
+
21
+ ## 2. Reporting a Vulnerability
22
+
23
+ If you discover a security issue, you are welcome to open a **private Gitea issue** or contact the maintainer directly. However, **no response timeline or resolution is guaranteed.** This project is maintained by a single human puppeteer, on their own terms.
24
+
25
+ ---
26
+
27
+ ## 3. Hardening Your Installation
28
+
29
+ You downloaded it. You ran it. That makes it your stack now, here's how to keep it clean.
30
+
31
+ ### Token Hygiene
32
+ - **Scope minimally:** Your `GITEA_TOKEN` should carry only the permissions Wraith needs, typically repository read/write. Do not use an admin-scoped token.
33
+ - **Rotate regularly:** Treat PATs like passwords. Rotate on a schedule or immediately following any suspected exposure.
34
+ - **Never commit tokens:** Ensure `.env` is listed in `.gitignore`. The Ghost Factory will not protect you from a pushed credential.
35
+
36
+ ### Environment Isolation
37
+ - Do not run Wraith in environments where `ps aux` or the process environment is visible to untrusted users.
38
+ - Prefer user-scoped shell exports over project-level `.env` files on shared systems.
39
+
40
+ ### Subprocess Awareness
41
+ - Token-injected URLs (e.g., `https://oauth2:{token}@git.domain.com/repo.git`) are passed directly to `git` subprocesses. On shared hardware, these may be transiently visible in the process list.
42
+ - On security-sensitive hosts, consider a **netrc-based credential helper** as an alternative to URL injection, which keeps the token out of the process argument list entirely.