xenfra 0.2.1__tar.gz → 0.2.3__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 (39) hide show
  1. xenfra-0.2.3/PKG-INFO +115 -0
  2. xenfra-0.2.3/README.md +83 -0
  3. {xenfra-0.2.1 → xenfra-0.2.3}/pyproject.toml +19 -20
  4. xenfra-0.2.3/src/xenfra/__init__.py +0 -0
  5. xenfra-0.2.3/src/xenfra/commands/__init__.py +3 -0
  6. xenfra-0.2.3/src/xenfra/commands/auth.py +186 -0
  7. xenfra-0.2.3/src/xenfra/commands/deployments.py +443 -0
  8. xenfra-0.2.3/src/xenfra/commands/intelligence.py +312 -0
  9. xenfra-0.2.3/src/xenfra/commands/projects.py +163 -0
  10. xenfra-0.2.3/src/xenfra/commands/security_cmd.py +235 -0
  11. xenfra-0.2.3/src/xenfra/main.py +70 -0
  12. xenfra-0.2.3/src/xenfra/utils/__init__.py +3 -0
  13. xenfra-0.2.3/src/xenfra/utils/auth.py +148 -0
  14. xenfra-0.2.3/src/xenfra/utils/codebase.py +86 -0
  15. xenfra-0.2.3/src/xenfra/utils/config.py +278 -0
  16. xenfra-0.2.3/src/xenfra/utils/security.py +350 -0
  17. xenfra-0.2.1/PKG-INFO +0 -95
  18. xenfra-0.2.1/README.md +0 -57
  19. xenfra-0.2.1/src/xenfra/__init__.py +0 -1
  20. xenfra-0.2.1/src/xenfra/api/auth.py +0 -51
  21. xenfra-0.2.1/src/xenfra/api/billing.py +0 -80
  22. xenfra-0.2.1/src/xenfra/api/connections.py +0 -163
  23. xenfra-0.2.1/src/xenfra/api/main.py +0 -175
  24. xenfra-0.2.1/src/xenfra/api/webhooks.py +0 -146
  25. xenfra-0.2.1/src/xenfra/cli/main.py +0 -211
  26. xenfra-0.2.1/src/xenfra/config.py +0 -24
  27. xenfra-0.2.1/src/xenfra/db/models.py +0 -51
  28. xenfra-0.2.1/src/xenfra/db/session.py +0 -17
  29. xenfra-0.2.1/src/xenfra/dependencies.py +0 -35
  30. xenfra-0.2.1/src/xenfra/dockerizer.py +0 -89
  31. xenfra-0.2.1/src/xenfra/engine.py +0 -292
  32. xenfra-0.2.1/src/xenfra/mcp_client.py +0 -149
  33. xenfra-0.2.1/src/xenfra/models.py +0 -54
  34. xenfra-0.2.1/src/xenfra/recipes.py +0 -23
  35. xenfra-0.2.1/src/xenfra/security.py +0 -58
  36. xenfra-0.2.1/src/xenfra/templates/Dockerfile.j2 +0 -25
  37. xenfra-0.2.1/src/xenfra/templates/cloud-init.sh.j2 +0 -68
  38. xenfra-0.2.1/src/xenfra/templates/docker-compose.yml.j2 +0 -33
  39. xenfra-0.2.1/src/xenfra/utils.py +0 -69
xenfra-0.2.3/PKG-INFO ADDED
@@ -0,0 +1,115 @@
1
+ Metadata-Version: 2.3
2
+ Name: xenfra
3
+ Version: 0.2.3
4
+ Summary: A 'Zen Mode' infrastructure engine for Python developers.
5
+ Author: xenfra-cloud
6
+ Author-email: xenfra-cloud <xenfracloud@gmail.com>
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Topic :: Software Development :: Build Tools
13
+ Classifier: Topic :: System :: Systems Administration
14
+ Requires-Dist: click>=8.1.7
15
+ Requires-Dist: rich>=14.2.0
16
+ Requires-Dist: sqlmodel>=0.0.16
17
+ Requires-Dist: python-digitalocean>=1.17.0
18
+ Requires-Dist: python-dotenv>=1.2.1
19
+ Requires-Dist: pyyaml>=6.0.1
20
+ Requires-Dist: fabric>=3.2.2
21
+ Requires-Dist: xenfra-sdk
22
+ Requires-Dist: httpx>=0.27.0
23
+ Requires-Dist: keyring>=25.7.0
24
+ Requires-Dist: keyrings-alt>=5.0.2
25
+ Requires-Dist: pytest>=8.0.0 ; extra == 'test'
26
+ Requires-Dist: pytest-mock>=3.12.0 ; extra == 'test'
27
+ Requires-Python: >=3.13
28
+ Project-URL: Homepage, https://github.com/xenfra-cloud/xenfra
29
+ Project-URL: Issues, https://github.com/xenfra-cloud/xenfra/issues
30
+ Provides-Extra: test
31
+ Description-Content-Type: text/markdown
32
+
33
+ # Xenfra CLI
34
+
35
+ ## Xenfra CLI: Deploy Python Apps with Zen Mode
36
+
37
+ The Xenfra CLI is a powerful and intuitive command-line interface designed to streamline the deployment of Python applications to DigitalOcean. Built with a "Zen Mode" philosophy, it automates complex infrastructure tasks, allowing developers to focus on writing code.
38
+
39
+ ### ✨ Key Features
40
+
41
+ * **Zero-Configuration Deployment:** Automatically detects your project's framework and dependencies.
42
+ * **AI-Powered Auto-Healing:** Diagnoses common deployment failures and suggests, or even applies, fixes automatically.
43
+ * **Real-time Monitoring:** View deployment status and stream live application logs directly from your terminal.
44
+ * **Integrated Project Management:** Easily list, view, and destroy your deployed projects.
45
+ * **Secure Authentication:** Uses OAuth2 PKCE flow for secure, token-based authentication.
46
+
47
+ ### 🚀 Quickstart
48
+
49
+ #### 1. Installation
50
+
51
+ Install the Xenfra CLI using `uv` (recommended) or `pip`:
52
+
53
+ ```bash
54
+ uv pip install xenfra-cli
55
+ # or
56
+ pip install xenfra-cli
57
+ ```
58
+
59
+ #### 2. Authentication
60
+
61
+ Log in to your Xenfra account. This will open your web browser to complete the OAuth2 flow.
62
+
63
+ ```bash
64
+ xenfra auth login
65
+ ```
66
+
67
+ #### 3. Initialize Your Project
68
+
69
+ Navigate to your Python project's root directory and run `init`. The CLI will scan your codebase, detect its characteristics, and generate a `xenfra.yaml` configuration file.
70
+
71
+ ```bash
72
+ cd your-python-project/
73
+ xenfra init
74
+ ```
75
+
76
+ #### 4. Deploy Your Application
77
+
78
+ Once `xenfra.yaml` is configured, deploy your application. The CLI will handle provisioning a DigitalOcean Droplet, setting up Docker, and deploying your code.
79
+
80
+ ```bash
81
+ xenfra deploy
82
+ ```
83
+
84
+ ### 📋 Usage Examples
85
+
86
+ * **Monitor Deployment Status:**
87
+ ```bash
88
+ xenfra status <deployment-id>
89
+ ```
90
+ * **Stream Application Logs:**
91
+ ```bash
92
+ xenfra logs <deployment-id>
93
+ ```
94
+ * **List Deployed Projects:**
95
+ ```bash
96
+ xenfra projects list
97
+ ```
98
+ * **Diagnose a Failed Deployment (AI-Powered):**
99
+ ```bash
100
+ xenfra diagnose <deployment-id>
101
+ # Or to diagnose from a log file:
102
+ xenfra diagnose --logs error.log
103
+ ```
104
+
105
+ ### 📚 Documentation
106
+
107
+ For more detailed information, advanced configurations, and API references, please refer to the [official Xenfra Documentation](https://docs.xenfra.com/cli) (Link will be updated upon final deployment).
108
+
109
+ ### 🤝 Contributing
110
+
111
+ We welcome contributions! Please see our [Contributing Guidelines](CONTRIBUTING.md) for more details.
112
+
113
+ ### 📄 License
114
+
115
+ This project is licensed under the [MIT License](LICENSE).
xenfra-0.2.3/README.md ADDED
@@ -0,0 +1,83 @@
1
+ # Xenfra CLI
2
+
3
+ ## Xenfra CLI: Deploy Python Apps with Zen Mode
4
+
5
+ The Xenfra CLI is a powerful and intuitive command-line interface designed to streamline the deployment of Python applications to DigitalOcean. Built with a "Zen Mode" philosophy, it automates complex infrastructure tasks, allowing developers to focus on writing code.
6
+
7
+ ### ✨ Key Features
8
+
9
+ * **Zero-Configuration Deployment:** Automatically detects your project's framework and dependencies.
10
+ * **AI-Powered Auto-Healing:** Diagnoses common deployment failures and suggests, or even applies, fixes automatically.
11
+ * **Real-time Monitoring:** View deployment status and stream live application logs directly from your terminal.
12
+ * **Integrated Project Management:** Easily list, view, and destroy your deployed projects.
13
+ * **Secure Authentication:** Uses OAuth2 PKCE flow for secure, token-based authentication.
14
+
15
+ ### 🚀 Quickstart
16
+
17
+ #### 1. Installation
18
+
19
+ Install the Xenfra CLI using `uv` (recommended) or `pip`:
20
+
21
+ ```bash
22
+ uv pip install xenfra-cli
23
+ # or
24
+ pip install xenfra-cli
25
+ ```
26
+
27
+ #### 2. Authentication
28
+
29
+ Log in to your Xenfra account. This will open your web browser to complete the OAuth2 flow.
30
+
31
+ ```bash
32
+ xenfra auth login
33
+ ```
34
+
35
+ #### 3. Initialize Your Project
36
+
37
+ Navigate to your Python project's root directory and run `init`. The CLI will scan your codebase, detect its characteristics, and generate a `xenfra.yaml` configuration file.
38
+
39
+ ```bash
40
+ cd your-python-project/
41
+ xenfra init
42
+ ```
43
+
44
+ #### 4. Deploy Your Application
45
+
46
+ Once `xenfra.yaml` is configured, deploy your application. The CLI will handle provisioning a DigitalOcean Droplet, setting up Docker, and deploying your code.
47
+
48
+ ```bash
49
+ xenfra deploy
50
+ ```
51
+
52
+ ### 📋 Usage Examples
53
+
54
+ * **Monitor Deployment Status:**
55
+ ```bash
56
+ xenfra status <deployment-id>
57
+ ```
58
+ * **Stream Application Logs:**
59
+ ```bash
60
+ xenfra logs <deployment-id>
61
+ ```
62
+ * **List Deployed Projects:**
63
+ ```bash
64
+ xenfra projects list
65
+ ```
66
+ * **Diagnose a Failed Deployment (AI-Powered):**
67
+ ```bash
68
+ xenfra diagnose <deployment-id>
69
+ # Or to diagnose from a log file:
70
+ xenfra diagnose --logs error.log
71
+ ```
72
+
73
+ ### 📚 Documentation
74
+
75
+ For more detailed information, advanced configurations, and API references, please refer to the [official Xenfra Documentation](https://docs.xenfra.com/cli) (Link will be updated upon final deployment).
76
+
77
+ ### 🤝 Contributing
78
+
79
+ We welcome contributions! Please see our [Contributing Guidelines](CONTRIBUTING.md) for more details.
80
+
81
+ ### 📄 License
82
+
83
+ This project is licensed under the [MIT License](LICENSE).
@@ -1,12 +1,12 @@
1
1
  [project]
2
2
  name = "xenfra"
3
- version = "0.2.1"
3
+ version = "0.2.3"
4
4
  description = "A 'Zen Mode' infrastructure engine for Python developers."
5
5
  readme = "README.md"
6
6
  authors = [
7
7
  { name = "xenfra-cloud", email = "xenfracloud@gmail.com" }
8
8
  ]
9
- requires-python = ">=3.13"
9
+
10
10
  classifiers = [
11
11
  "Programming Language :: Python :: 3",
12
12
  "License :: OSI Approved :: MIT License",
@@ -16,39 +16,38 @@ classifiers = [
16
16
  "Topic :: Software Development :: Build Tools",
17
17
  "Topic :: System :: Systems Administration",
18
18
  ]
19
+
19
20
  dependencies = [
20
- "fabric>=3.2.2",
21
- "python-digitalocean>=1.17.0",
22
- "python-dotenv>=1.2.1",
23
- "rich>=14.2.0",
24
- "fastapi>=0.110.0",
25
- "uvicorn[standard]>=0.27.1",
26
21
  "click>=8.1.7",
22
+ "rich>=14.2.0",
27
23
  "sqlmodel>=0.0.16",
28
- "psycopg2-binary>=2.9.9",
29
- "python-jose[cryptography]>=3.3.0",
30
- "passlib>=1.7.4", # No longer need [bcrypt] extra
24
+ "python-digitalocean>=1.17.0",
25
+ "python-dotenv>=1.2.1",
26
+ "pyyaml>=6.0.1",
27
+ "fabric>=3.2.2",
28
+ "xenfra-sdk",
31
29
  "httpx>=0.27.0",
32
- "PyYAML>=6.0.1", # Explicitly add bcrypt backend
33
- "python-multipart>=0.0.21",
34
- "bcrypt==4.0.1",
35
- "Jinja2>=3.1.3",
36
- "pytest>=9.0.2",
30
+ "keyring>=25.7.0",
31
+ "keyrings.alt>=5.0.2",
37
32
  ]
33
+ requires-python = ">=3.13"
34
+
35
+ [tool.uv.sources]
36
+ xenfra-sdk = { workspace = true }
38
37
 
39
38
  [project.urls]
40
39
  Homepage = "https://github.com/xenfra-cloud/xenfra"
41
40
  Issues = "https://github.com/xenfra-cloud/xenfra/issues"
42
41
 
43
- [project.scripts]
44
- xenfra = "xenfra.cli.main:main"
45
-
46
42
  [project.optional-dependencies]
47
43
  test = [
48
44
  "pytest>=8.0.0",
49
45
  "pytest-mock>=3.12.0",
50
46
  ]
51
47
 
48
+ [project.scripts]
49
+ xenfra = "xenfra_cli.main:main"
50
+
52
51
  [build-system]
53
52
  requires = ["uv_build>=0.9.18,<0.10.0"]
54
- build-backend = "uv_build"
53
+ build-backend = "uv_build"
File without changes
@@ -0,0 +1,3 @@
1
+ """
2
+ CLI command modules for Xenfra.
3
+ """
@@ -0,0 +1,186 @@
1
+ """
2
+ Authentication commands for Xenfra CLI.
3
+ """
4
+
5
+ import base64
6
+ import hashlib
7
+ import secrets
8
+ import urllib.parse
9
+ import webbrowser
10
+ from http.server import HTTPServer
11
+
12
+ import click
13
+ import httpx
14
+ import keyring
15
+ from rich.console import Console
16
+
17
+ from ..utils.auth import (
18
+ API_BASE_URL,
19
+ CLI_CLIENT_ID,
20
+ CLI_LOCAL_SERVER_END_PORT,
21
+ CLI_LOCAL_SERVER_START_PORT,
22
+ CLI_REDIRECT_PATH,
23
+ SERVICE_ID,
24
+ AuthCallbackHandler,
25
+ clear_tokens,
26
+ get_auth_token,
27
+ )
28
+
29
+ console = Console()
30
+
31
+
32
+ @click.group()
33
+ def auth():
34
+ """Authentication commands."""
35
+ pass
36
+
37
+
38
+ @auth.command()
39
+ def login():
40
+ """Login to Xenfra using OAuth2 PKCE flow."""
41
+ global oauth_data
42
+ oauth_data = {"code": None, "state": None, "error": None}
43
+
44
+ # 1. Generate PKCE parameters
45
+ code_verifier = secrets.token_urlsafe(96)
46
+ code_challenge = (
47
+ base64.urlsafe_b64encode(hashlib.sha256(code_verifier.encode()).digest())
48
+ .decode()
49
+ .rstrip("=")
50
+ )
51
+
52
+ # 2. Generate state for CSRF protection
53
+ state = secrets.token_urlsafe(32)
54
+
55
+ # 3. Start local HTTP server
56
+ server_port = None
57
+ httpd_instance = None
58
+ for port in range(CLI_LOCAL_SERVER_START_PORT, CLI_LOCAL_SERVER_END_PORT + 1):
59
+ try:
60
+ server_address = ("127.0.0.1", port)
61
+ httpd_instance = HTTPServer(server_address, AuthCallbackHandler)
62
+ server_port = port
63
+ break
64
+ except OSError:
65
+ continue
66
+
67
+ if not server_port:
68
+ console.print(
69
+ f"[bold red]Error: No available ports in range {CLI_LOCAL_SERVER_START_PORT}-{CLI_LOCAL_SERVER_END_PORT}[/bold red]"
70
+ )
71
+ return
72
+
73
+ redirect_uri = f"http://localhost:{server_port}{CLI_REDIRECT_PATH}"
74
+
75
+ # 4. Construct Authorization URL
76
+ auth_url = (
77
+ f"{API_BASE_URL}/auth/authorize?"
78
+ f"client_id={CLI_CLIENT_ID}&"
79
+ f"redirect_uri={urllib.parse.quote(redirect_uri)}&"
80
+ f"response_type=code&"
81
+ f"scope={urllib.parse.quote('openid profile')}&"
82
+ f"state={state}&"
83
+ f"code_challenge={code_challenge}&"
84
+ f"code_challenge_method=S256"
85
+ )
86
+
87
+ console.print("[bold blue]Opening browser for login...[/bold blue]")
88
+ console.print(
89
+ f"[dim]If browser doesn't open, navigate to:[/dim]\n[link={auth_url}]{auth_url}[/link]"
90
+ )
91
+ webbrowser.open(auth_url)
92
+
93
+ # 5. Run local server to capture redirect
94
+ try:
95
+ AuthCallbackHandler.server = httpd_instance # type: ignore
96
+ httpd_instance.handle_request() # type: ignore
97
+ console.print("[dim]Local OAuth server shut down.[/dim]")
98
+ except Exception as e:
99
+ console.print(f"[bold red]Error running OAuth server: {e}[/bold red]")
100
+ if httpd_instance:
101
+ httpd_instance.server_close()
102
+ return
103
+
104
+ if oauth_data["error"]:
105
+ console.print(f"[bold red]Login failed: {oauth_data['error']}[/bold red]")
106
+ return
107
+
108
+ if not oauth_data["code"]:
109
+ console.print("[bold red]Login failed: No authorization code received.[/bold red]")
110
+ return
111
+
112
+ # 6. Verify state
113
+ if oauth_data["state"] != state:
114
+ console.print("[bold red]Login failed: State mismatch (possible CSRF attack)[/bold red]")
115
+ return
116
+
117
+ # 7. Exchange code for tokens
118
+ console.print("[bold cyan]Exchanging authorization code for tokens...[/bold cyan]")
119
+ try:
120
+ with httpx.Client() as client:
121
+ response = client.post(
122
+ f"{API_BASE_URL}/auth/token",
123
+ data={
124
+ "grant_type": "authorization_code",
125
+ "client_id": CLI_CLIENT_ID,
126
+ "code": oauth_data["code"],
127
+ "code_verifier": code_verifier,
128
+ "redirect_uri": redirect_uri,
129
+ },
130
+ )
131
+ response.raise_for_status()
132
+ token_data = response.json()
133
+ access_token = token_data.get("access_token")
134
+ refresh_token = token_data.get("refresh_token")
135
+
136
+ if access_token and refresh_token:
137
+ keyring.set_password(SERVICE_ID, "access_token", access_token)
138
+ keyring.set_password(SERVICE_ID, "refresh_token", refresh_token)
139
+ console.print("[bold green]Login successful! Tokens saved securely.[/bold green]")
140
+ else:
141
+ console.print("[bold red]Login failed: No tokens received.[/bold red]")
142
+ except httpx.RequestError as exc:
143
+ console.print(f"[bold red]Token exchange failed: {exc}[/bold red]")
144
+ except httpx.HTTPStatusError as exc:
145
+ console.print(f"[bold red]Token exchange failed: {exc.response.status_code}[/bold red]")
146
+
147
+
148
+ @auth.command()
149
+ def logout():
150
+ """Logout and clear stored tokens."""
151
+ clear_tokens()
152
+ console.print("[bold green]Logged out successfully.[/bold green]")
153
+
154
+
155
+ @auth.command()
156
+ @click.option("--token", is_flag=True, help="Show access token")
157
+ def whoami(token):
158
+ """Show current authenticated user."""
159
+ access_token = get_auth_token()
160
+
161
+ if not access_token:
162
+ console.print("[bold red]Not logged in. Run 'xenfra login' first.[/bold red]")
163
+ return
164
+
165
+ try:
166
+ from jose import jwt
167
+
168
+ # For display purposes only, in a CLI context where the token has just
169
+ # been retrieved from a secure source (keyring), we can disable
170
+ # signature verification.
171
+ #
172
+ # SECURITY BEST PRACTICE: In a real application, especially a server,
173
+ # you would fetch the public key from the SSO's JWKS endpoint and
174
+ # fully verify the token's signature to ensure its integrity.
175
+ claims = jwt.decode(
176
+ access_token, options={"verify_signature": False} # OK for local display
177
+ )
178
+
179
+ console.print("[bold green]Logged in as:[/bold green]")
180
+ console.print(f" User ID: {claims.get('sub')}")
181
+ console.print(f" Email: {claims.get('email', 'N/A')}")
182
+
183
+ if token:
184
+ console.print(f"\n[dim]Access Token:[/dim]\n{access_token}")
185
+ except Exception as e:
186
+ console.print(f"[bold red]Failed to decode token: {e}[/bold red]")