@plures/praxis 0.2.0
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.
- package/FRAMEWORK.md +420 -0
- package/LICENSE +21 -0
- package/README.md +1310 -0
- package/dist/adapters/cli.d.ts +43 -0
- package/dist/adapters/cli.d.ts.map +1 -0
- package/dist/adapters/cli.js +126 -0
- package/dist/adapters/cli.js.map +1 -0
- package/dist/cli/commands/auth.d.ts +26 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +233 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/cloud.d.ts +27 -0
- package/dist/cli/commands/cloud.d.ts.map +1 -0
- package/dist/cli/commands/cloud.js +232 -0
- package/dist/cli/commands/cloud.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +25 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +168 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +179 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cloud/auth.d.ts +51 -0
- package/dist/cloud/auth.d.ts.map +1 -0
- package/dist/cloud/auth.js +194 -0
- package/dist/cloud/auth.js.map +1 -0
- package/dist/cloud/billing.d.ts +184 -0
- package/dist/cloud/billing.d.ts.map +1 -0
- package/dist/cloud/billing.js +179 -0
- package/dist/cloud/billing.js.map +1 -0
- package/dist/cloud/client.d.ts +39 -0
- package/dist/cloud/client.d.ts.map +1 -0
- package/dist/cloud/client.js +176 -0
- package/dist/cloud/client.js.map +1 -0
- package/dist/cloud/index.d.ts +44 -0
- package/dist/cloud/index.d.ts.map +1 -0
- package/dist/cloud/index.js +44 -0
- package/dist/cloud/index.js.map +1 -0
- package/dist/cloud/marketplace.d.ts +166 -0
- package/dist/cloud/marketplace.d.ts.map +1 -0
- package/dist/cloud/marketplace.js +159 -0
- package/dist/cloud/marketplace.js.map +1 -0
- package/dist/cloud/provisioning.d.ts +110 -0
- package/dist/cloud/provisioning.d.ts.map +1 -0
- package/dist/cloud/provisioning.js +148 -0
- package/dist/cloud/provisioning.js.map +1 -0
- package/dist/cloud/relay/endpoints.d.ts +62 -0
- package/dist/cloud/relay/endpoints.d.ts.map +1 -0
- package/dist/cloud/relay/endpoints.js +217 -0
- package/dist/cloud/relay/endpoints.js.map +1 -0
- package/dist/cloud/relay/health/index.d.ts +5 -0
- package/dist/cloud/relay/health/index.d.ts.map +1 -0
- package/dist/cloud/relay/health/index.js +9 -0
- package/dist/cloud/relay/health/index.js.map +1 -0
- package/dist/cloud/relay/stats/index.d.ts +5 -0
- package/dist/cloud/relay/stats/index.d.ts.map +1 -0
- package/dist/cloud/relay/stats/index.js +9 -0
- package/dist/cloud/relay/stats/index.js.map +1 -0
- package/dist/cloud/relay/sync/index.d.ts +5 -0
- package/dist/cloud/relay/sync/index.d.ts.map +1 -0
- package/dist/cloud/relay/sync/index.js +9 -0
- package/dist/cloud/relay/sync/index.js.map +1 -0
- package/dist/cloud/relay/usage/index.d.ts +5 -0
- package/dist/cloud/relay/usage/index.d.ts.map +1 -0
- package/dist/cloud/relay/usage/index.js +9 -0
- package/dist/cloud/relay/usage/index.js.map +1 -0
- package/dist/cloud/sponsors.d.ts +81 -0
- package/dist/cloud/sponsors.d.ts.map +1 -0
- package/dist/cloud/sponsors.js +130 -0
- package/dist/cloud/sponsors.js.map +1 -0
- package/dist/cloud/types.d.ts +169 -0
- package/dist/cloud/types.d.ts.map +1 -0
- package/dist/cloud/types.js +7 -0
- package/dist/cloud/types.js.map +1 -0
- package/dist/components/index.d.ts +43 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +17 -0
- package/dist/components/index.js.map +1 -0
- package/dist/core/actors.d.ts +95 -0
- package/dist/core/actors.d.ts.map +1 -0
- package/dist/core/actors.js +158 -0
- package/dist/core/actors.js.map +1 -0
- package/dist/core/component/generator.d.ts +122 -0
- package/dist/core/component/generator.d.ts.map +1 -0
- package/dist/core/component/generator.js +307 -0
- package/dist/core/component/generator.js.map +1 -0
- package/dist/core/engine.d.ts +92 -0
- package/dist/core/engine.d.ts.map +1 -0
- package/dist/core/engine.js +199 -0
- package/dist/core/engine.js.map +1 -0
- package/dist/core/introspection.d.ts +141 -0
- package/dist/core/introspection.d.ts.map +1 -0
- package/dist/core/introspection.js +208 -0
- package/dist/core/introspection.js.map +1 -0
- package/dist/core/logic/generator.d.ts +76 -0
- package/dist/core/logic/generator.d.ts.map +1 -0
- package/dist/core/logic/generator.js +339 -0
- package/dist/core/logic/generator.js.map +1 -0
- package/dist/core/pluresdb/generator.d.ts +58 -0
- package/dist/core/pluresdb/generator.d.ts.map +1 -0
- package/dist/core/pluresdb/generator.js +162 -0
- package/dist/core/pluresdb/generator.js.map +1 -0
- package/dist/core/protocol.d.ts +121 -0
- package/dist/core/protocol.d.ts.map +1 -0
- package/dist/core/protocol.js +46 -0
- package/dist/core/protocol.js.map +1 -0
- package/dist/core/rules.d.ts +120 -0
- package/dist/core/rules.d.ts.map +1 -0
- package/dist/core/rules.js +81 -0
- package/dist/core/rules.js.map +1 -0
- package/dist/core/schema/loader.d.ts +47 -0
- package/dist/core/schema/loader.d.ts.map +1 -0
- package/dist/core/schema/loader.js +189 -0
- package/dist/core/schema/loader.js.map +1 -0
- package/dist/core/schema/normalize.d.ts +72 -0
- package/dist/core/schema/normalize.d.ts.map +1 -0
- package/dist/core/schema/normalize.js +190 -0
- package/dist/core/schema/normalize.js.map +1 -0
- package/dist/core/schema/types.d.ts +370 -0
- package/dist/core/schema/types.d.ts.map +1 -0
- package/dist/core/schema/types.js +161 -0
- package/dist/core/schema/types.js.map +1 -0
- package/dist/dsl/index.d.ts +152 -0
- package/dist/dsl/index.d.ts.map +1 -0
- package/dist/dsl/index.js +132 -0
- package/dist/dsl/index.js.map +1 -0
- package/dist/dsl.d.ts +124 -0
- package/dist/dsl.d.ts.map +1 -0
- package/dist/dsl.js +130 -0
- package/dist/dsl.js.map +1 -0
- package/dist/examples/advanced-todo/index.d.ts +55 -0
- package/dist/examples/advanced-todo/index.d.ts.map +1 -0
- package/dist/examples/advanced-todo/index.js +222 -0
- package/dist/examples/advanced-todo/index.js.map +1 -0
- package/dist/examples/auth-basic/index.d.ts +17 -0
- package/dist/examples/auth-basic/index.d.ts.map +1 -0
- package/dist/examples/auth-basic/index.js +122 -0
- package/dist/examples/auth-basic/index.js.map +1 -0
- package/dist/examples/cart/index.d.ts +19 -0
- package/dist/examples/cart/index.d.ts.map +1 -0
- package/dist/examples/cart/index.js +202 -0
- package/dist/examples/cart/index.js.map +1 -0
- package/dist/examples/hero-ecommerce/index.d.ts +39 -0
- package/dist/examples/hero-ecommerce/index.d.ts.map +1 -0
- package/dist/examples/hero-ecommerce/index.js +506 -0
- package/dist/examples/hero-ecommerce/index.js.map +1 -0
- package/dist/examples/svelte-counter/index.d.ts +31 -0
- package/dist/examples/svelte-counter/index.d.ts.map +1 -0
- package/dist/examples/svelte-counter/index.js +123 -0
- package/dist/examples/svelte-counter/index.js.map +1 -0
- package/dist/flows.d.ts +125 -0
- package/dist/flows.d.ts.map +1 -0
- package/dist/flows.js +160 -0
- package/dist/flows.js.map +1 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/pluresdb.d.ts +56 -0
- package/dist/integrations/pluresdb.d.ts.map +1 -0
- package/dist/integrations/pluresdb.js +46 -0
- package/dist/integrations/pluresdb.js.map +1 -0
- package/dist/integrations/svelte.d.ts +306 -0
- package/dist/integrations/svelte.d.ts.map +1 -0
- package/dist/integrations/svelte.js +447 -0
- package/dist/integrations/svelte.js.map +1 -0
- package/dist/registry.d.ts +94 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +181 -0
- package/dist/registry.js.map +1 -0
- package/dist/runtime/terminal-adapter.d.ts +105 -0
- package/dist/runtime/terminal-adapter.d.ts.map +1 -0
- package/dist/runtime/terminal-adapter.js +113 -0
- package/dist/runtime/terminal-adapter.js.map +1 -0
- package/dist/step.d.ts +34 -0
- package/dist/step.d.ts.map +1 -0
- package/dist/step.js +111 -0
- package/dist/step.js.map +1 -0
- package/dist/types.d.ts +63 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/docs/MONETIZATION.md +394 -0
- package/docs/TERMINAL_NODE.md +588 -0
- package/docs/guides/canvas.md +389 -0
- package/docs/guides/getting-started.md +347 -0
- package/docs/guides/history-state-pattern.md +618 -0
- package/docs/guides/orchestration.md +617 -0
- package/docs/guides/parallel-state-pattern.md +767 -0
- package/docs/guides/svelte-integration.md +691 -0
- package/package.json +96 -0
- package/src/__tests__/actors.test.ts +270 -0
- package/src/__tests__/billing.test.ts +175 -0
- package/src/__tests__/cloud.test.ts +247 -0
- package/src/__tests__/dsl.test.ts +154 -0
- package/src/__tests__/edge-cases.test.ts +475 -0
- package/src/__tests__/engine.test.ts +137 -0
- package/src/__tests__/generators.test.ts +270 -0
- package/src/__tests__/introspection.test.ts +321 -0
- package/src/__tests__/protocol.test.ts +40 -0
- package/src/__tests__/provisioning.test.ts +162 -0
- package/src/__tests__/schema.test.ts +241 -0
- package/src/__tests__/svelte-integration.test.ts +431 -0
- package/src/__tests__/terminal-node.test.ts +352 -0
- package/src/adapters/cli.ts +175 -0
- package/src/cli/commands/auth.ts +271 -0
- package/src/cli/commands/cloud.ts +281 -0
- package/src/cli/commands/generate.ts +225 -0
- package/src/cli/index.ts +190 -0
- package/src/cloud/README.md +383 -0
- package/src/cloud/auth.ts +245 -0
- package/src/cloud/billing.ts +336 -0
- package/src/cloud/client.ts +221 -0
- package/src/cloud/index.ts +121 -0
- package/src/cloud/marketplace.ts +303 -0
- package/src/cloud/provisioning.ts +254 -0
- package/src/cloud/relay/endpoints.ts +307 -0
- package/src/cloud/relay/health/function.json +17 -0
- package/src/cloud/relay/health/index.ts +10 -0
- package/src/cloud/relay/host.json +15 -0
- package/src/cloud/relay/local.settings.json +8 -0
- package/src/cloud/relay/stats/function.json +17 -0
- package/src/cloud/relay/stats/index.ts +10 -0
- package/src/cloud/relay/sync/function.json +17 -0
- package/src/cloud/relay/sync/index.ts +10 -0
- package/src/cloud/relay/usage/function.json +17 -0
- package/src/cloud/relay/usage/index.ts +10 -0
- package/src/cloud/sponsors.ts +213 -0
- package/src/cloud/types.ts +198 -0
- package/src/components/README.md +125 -0
- package/src/components/TerminalNode.svelte +457 -0
- package/src/components/index.ts +46 -0
- package/src/core/actors.ts +205 -0
- package/src/core/component/generator.ts +432 -0
- package/src/core/engine.ts +243 -0
- package/src/core/introspection.ts +329 -0
- package/src/core/logic/generator.ts +420 -0
- package/src/core/pluresdb/generator.ts +229 -0
- package/src/core/protocol.ts +132 -0
- package/src/core/rules.ts +167 -0
- package/src/core/schema/loader.ts +247 -0
- package/src/core/schema/normalize.ts +322 -0
- package/src/core/schema/types.ts +557 -0
- package/src/dsl/index.ts +218 -0
- package/src/dsl.ts +214 -0
- package/src/examples/advanced-todo/App.svelte +506 -0
- package/src/examples/advanced-todo/README.md +371 -0
- package/src/examples/advanced-todo/index.ts +309 -0
- package/src/examples/auth-basic/index.ts +163 -0
- package/src/examples/cart/index.ts +259 -0
- package/src/examples/hero-ecommerce/index.ts +657 -0
- package/src/examples/svelte-counter/index.ts +168 -0
- package/src/flows.ts +268 -0
- package/src/index.ts +154 -0
- package/src/integrations/pluresdb.ts +93 -0
- package/src/integrations/svelte.ts +617 -0
- package/src/registry.ts +223 -0
- package/src/runtime/terminal-adapter.ts +175 -0
- package/src/step.ts +151 -0
- package/src/types.ts +70 -0
- package/templates/basic-app/README.md +147 -0
- package/templates/fullstack-app/README.md +279 -0
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
# GitHub-Based Monetization
|
|
2
|
+
|
|
3
|
+
This document describes the GitHub-native monetization implementation for Praxis Cloud.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Praxis Cloud uses GitHub as the exclusive authentication and billing provider, aligning with the Microsoft partnership constraint. This enables:
|
|
8
|
+
|
|
9
|
+
- **GitHub OAuth** for secure authentication
|
|
10
|
+
- **GitHub Sponsors** for recurring subscriptions
|
|
11
|
+
- **GitHub Marketplace** for enterprise SaaS billing (preparatory)
|
|
12
|
+
- **Auto-provisioning** based on GitHub identity
|
|
13
|
+
|
|
14
|
+
## Architecture
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
┌─────────────────┐
|
|
18
|
+
│ GitHub User │
|
|
19
|
+
└────────┬────────┘
|
|
20
|
+
│ OAuth Device Flow
|
|
21
|
+
▼
|
|
22
|
+
┌─────────────────┐
|
|
23
|
+
│ Praxis CLI │
|
|
24
|
+
│ praxis login │
|
|
25
|
+
└────────┬────────┘
|
|
26
|
+
│ GitHub Token
|
|
27
|
+
▼
|
|
28
|
+
┌─────────────────┐ ┌──────────────────┐
|
|
29
|
+
│ Praxis Cloud │────▶│ GitHub Sponsors │
|
|
30
|
+
│ Relay Service │ │ API │
|
|
31
|
+
└────────┬────────┘ └──────────────────┘
|
|
32
|
+
│
|
|
33
|
+
▼
|
|
34
|
+
┌─────────────────┐
|
|
35
|
+
│ Auto-Provision │
|
|
36
|
+
│ Tenant/Storage │
|
|
37
|
+
└─────────────────┘
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Subscription Tiers
|
|
41
|
+
|
|
42
|
+
### Free Tier
|
|
43
|
+
- **Cost**: Free
|
|
44
|
+
- **Limits**:
|
|
45
|
+
- 1,000 syncs/month
|
|
46
|
+
- 10 MB storage
|
|
47
|
+
- 1 app/project
|
|
48
|
+
- Community support
|
|
49
|
+
|
|
50
|
+
### Solo Tier ($5/month via GitHub Sponsors)
|
|
51
|
+
- **Limits**:
|
|
52
|
+
- 50,000 syncs/month
|
|
53
|
+
- 1 GB storage
|
|
54
|
+
- 10 apps/projects
|
|
55
|
+
- Standard support
|
|
56
|
+
|
|
57
|
+
### Team Tier ($20/month via GitHub Sponsors)
|
|
58
|
+
- **Limits**:
|
|
59
|
+
- 500,000 syncs/month
|
|
60
|
+
- 10 GB storage
|
|
61
|
+
- 50 apps/projects
|
|
62
|
+
- 10 team members
|
|
63
|
+
- Standard support
|
|
64
|
+
|
|
65
|
+
### Enterprise Tier ($50/month via GitHub Sponsors/Marketplace)
|
|
66
|
+
- **Limits**:
|
|
67
|
+
- 5,000,000 syncs/month
|
|
68
|
+
- 100 GB storage
|
|
69
|
+
- 1,000 apps/projects
|
|
70
|
+
- Unlimited team members
|
|
71
|
+
- Priority support
|
|
72
|
+
- SLA guarantees
|
|
73
|
+
|
|
74
|
+
## Authentication Flow
|
|
75
|
+
|
|
76
|
+
### 1. CLI Authentication
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Using device flow (recommended)
|
|
80
|
+
praxis login
|
|
81
|
+
|
|
82
|
+
# Using personal access token
|
|
83
|
+
praxis login --token ghp_xxxxx
|
|
84
|
+
|
|
85
|
+
# Check authentication
|
|
86
|
+
praxis whoami
|
|
87
|
+
|
|
88
|
+
# Logout
|
|
89
|
+
praxis logout
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 2. Device Flow Process
|
|
93
|
+
|
|
94
|
+
1. User runs `praxis login`
|
|
95
|
+
2. CLI requests device code from GitHub
|
|
96
|
+
3. User visits verification URL and enters code
|
|
97
|
+
4. CLI polls for access token
|
|
98
|
+
5. Token and user info stored locally in `~/.praxis/auth.json`
|
|
99
|
+
6. CLI checks GitHub Sponsors status
|
|
100
|
+
7. Auto-provisions tenant and storage
|
|
101
|
+
|
|
102
|
+
### 3. Programmatic Authentication
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import { authenticateWithDeviceFlow } from "@plures/praxis/cloud";
|
|
106
|
+
|
|
107
|
+
const result = await authenticateWithDeviceFlow("YOUR_CLIENT_ID");
|
|
108
|
+
if (result.success) {
|
|
109
|
+
console.log(`Authenticated as ${result.user?.login}`);
|
|
110
|
+
console.log(`Token: ${result.token}`);
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## GitHub App Setup
|
|
115
|
+
|
|
116
|
+
### Creating the GitHub App
|
|
117
|
+
|
|
118
|
+
1. Visit https://github.com/settings/apps/new
|
|
119
|
+
2. Use the manifest at `github/app/manifest.yml`
|
|
120
|
+
3. Configure OAuth callback URL
|
|
121
|
+
4. Enable webhooks for sponsorship events
|
|
122
|
+
5. Generate and store client secret
|
|
123
|
+
|
|
124
|
+
### Required Permissions
|
|
125
|
+
|
|
126
|
+
- **User permissions**: `emails:read`
|
|
127
|
+
- **OAuth scopes**: `read:user`, `user:email`
|
|
128
|
+
- **Webhook events**: `sponsorship`, `marketplace_purchase`
|
|
129
|
+
|
|
130
|
+
### Environment Variables
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# GitHub OAuth
|
|
134
|
+
GITHUB_CLIENT_ID=your_client_id
|
|
135
|
+
GITHUB_CLIENT_SECRET=your_client_secret
|
|
136
|
+
|
|
137
|
+
# Praxis Cloud
|
|
138
|
+
PRAXIS_RELAY_ENDPOINT=https://praxis-relay.azurewebsites.net
|
|
139
|
+
PRAXIS_APP_ID=your_app_id
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## GitHub Sponsors Integration
|
|
143
|
+
|
|
144
|
+
### Setting Up Sponsors Tiers
|
|
145
|
+
|
|
146
|
+
1. Enable GitHub Sponsors for your organization
|
|
147
|
+
2. Create tiers matching Praxis pricing:
|
|
148
|
+
- Solo: $5/month
|
|
149
|
+
- Team: $20/month
|
|
150
|
+
- Enterprise: $50/month
|
|
151
|
+
3. Configure webhook to notify relay service
|
|
152
|
+
|
|
153
|
+
### Checking Subscription Status
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { createSponsorsClient } from "@plures/praxis/cloud";
|
|
157
|
+
|
|
158
|
+
const client = createSponsorsClient(githubToken);
|
|
159
|
+
const subscription = await client.getSubscription("username");
|
|
160
|
+
|
|
161
|
+
console.log(`Tier: ${subscription.tier}`);
|
|
162
|
+
console.log(`Status: ${subscription.status}`);
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Handling Sponsorship Events
|
|
166
|
+
|
|
167
|
+
Webhook payload example:
|
|
168
|
+
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"action": "created",
|
|
172
|
+
"sponsorship": {
|
|
173
|
+
"sponsor": {
|
|
174
|
+
"login": "username",
|
|
175
|
+
"id": 12345
|
|
176
|
+
},
|
|
177
|
+
"tier": {
|
|
178
|
+
"name": "Solo",
|
|
179
|
+
"monthly_price_in_cents": 500
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## GitHub Marketplace Integration (Preparatory)
|
|
186
|
+
|
|
187
|
+
### Marketplace Plans
|
|
188
|
+
|
|
189
|
+
Plans are pre-configured in `src/cloud/marketplace.ts`:
|
|
190
|
+
|
|
191
|
+
- **Praxis Cloud Solo**: $5/month or $50/year
|
|
192
|
+
- **Praxis Cloud Team**: $20/month or $200/year
|
|
193
|
+
- **Praxis Cloud Enterprise**: $50/month or $500/year
|
|
194
|
+
|
|
195
|
+
### Marketplace Listing
|
|
196
|
+
|
|
197
|
+
See `github/marketplace/` for listing templates and screenshots.
|
|
198
|
+
|
|
199
|
+
### Webhook Handler
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
import { createMarketplaceClient } from "@plures/praxis/cloud";
|
|
203
|
+
|
|
204
|
+
const client = createMarketplaceClient(githubToken);
|
|
205
|
+
|
|
206
|
+
// Handle webhook event
|
|
207
|
+
app.post("/webhook/marketplace", (req, res) => {
|
|
208
|
+
const event = req.body;
|
|
209
|
+
const result = client.handleWebhookEvent(event);
|
|
210
|
+
|
|
211
|
+
if (result) {
|
|
212
|
+
// Provision or update tenant
|
|
213
|
+
console.log(`User ${result.userLogin} subscribed to ${result.subscription.tier}`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
res.status(200).send("OK");
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Auto-Provisioning
|
|
221
|
+
|
|
222
|
+
### Tenant Creation
|
|
223
|
+
|
|
224
|
+
When a user authenticates, a tenant is automatically provisioned:
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
import { provisionTenant, createTenant } from "@plures/praxis/cloud";
|
|
228
|
+
|
|
229
|
+
const result = await provisionTenant(githubUser, subscription);
|
|
230
|
+
|
|
231
|
+
if (result.success) {
|
|
232
|
+
console.log(`Tenant ID: ${result.tenant.id}`);
|
|
233
|
+
console.log(`Storage: ${result.tenant.storageNamespace}`);
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Storage Namespace
|
|
238
|
+
|
|
239
|
+
Storage namespaces follow Azure Blob Storage naming rules:
|
|
240
|
+
|
|
241
|
+
- Format: `gh-{username}-{hash}`
|
|
242
|
+
- Example: `gh-testuser-0009ix`
|
|
243
|
+
- Lowercase, alphanumeric, hyphens only
|
|
244
|
+
- 3-63 characters
|
|
245
|
+
|
|
246
|
+
### Access Control
|
|
247
|
+
|
|
248
|
+
Access to cloud features is controlled by subscription tier:
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
import { hasAccessToTier, SubscriptionTier } from "@plures/praxis/cloud";
|
|
252
|
+
|
|
253
|
+
if (hasAccessToTier(subscription, SubscriptionTier.TEAM)) {
|
|
254
|
+
// Allow team features
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Usage Tracking
|
|
259
|
+
|
|
260
|
+
### Checking Usage
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
praxis cloud usage
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Output:
|
|
267
|
+
```
|
|
268
|
+
App ID: my-app
|
|
269
|
+
|
|
270
|
+
Metrics:
|
|
271
|
+
Total Syncs: 1,234
|
|
272
|
+
Events Forwarded: 5,678
|
|
273
|
+
Facts Synced: 12,345
|
|
274
|
+
Storage Used: 45.67 KB
|
|
275
|
+
|
|
276
|
+
Period: 720.0 hours
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Enforcing Limits
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
import { checkUsageLimits } from "@plures/praxis/cloud";
|
|
283
|
+
|
|
284
|
+
const result = checkUsageLimits(subscription, {
|
|
285
|
+
syncCount: 1500,
|
|
286
|
+
storageBytes: 15 * 1024 * 1024,
|
|
287
|
+
teamMembers: 1,
|
|
288
|
+
appCount: 2,
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
if (!result.withinLimits) {
|
|
292
|
+
console.error("Usage limits exceeded:");
|
|
293
|
+
result.violations.forEach(v => console.error(` - ${v}`));
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## Security
|
|
298
|
+
|
|
299
|
+
### Token Storage
|
|
300
|
+
|
|
301
|
+
Authentication tokens are stored securely:
|
|
302
|
+
|
|
303
|
+
- **Location**: `~/.praxis/auth.json`
|
|
304
|
+
- **Permissions**: `0600` (owner read/write only)
|
|
305
|
+
- **Contents**: Encrypted in production
|
|
306
|
+
|
|
307
|
+
### Best Practices
|
|
308
|
+
|
|
309
|
+
1. **Never commit tokens** to source control
|
|
310
|
+
2. **Rotate tokens regularly**
|
|
311
|
+
3. **Use environment variables** for CI/CD
|
|
312
|
+
4. **Revoke tokens** when no longer needed
|
|
313
|
+
5. **Use GitHub App tokens** for production services
|
|
314
|
+
|
|
315
|
+
## Development
|
|
316
|
+
|
|
317
|
+
### Local Testing
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
# Set up test environment
|
|
321
|
+
export GITHUB_CLIENT_ID=your_test_client_id
|
|
322
|
+
export GITHUB_TOKEN=ghp_test_token
|
|
323
|
+
|
|
324
|
+
# Run tests
|
|
325
|
+
npm test
|
|
326
|
+
|
|
327
|
+
# Test CLI commands
|
|
328
|
+
npm run build
|
|
329
|
+
node dist/cli/index.js login
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Mocking GitHub API
|
|
333
|
+
|
|
334
|
+
For tests, use mock responses:
|
|
335
|
+
|
|
336
|
+
```typescript
|
|
337
|
+
// Mock GitHub API
|
|
338
|
+
vi.mock("../cloud/sponsors.js", () => ({
|
|
339
|
+
createSponsorsClient: vi.fn(() => ({
|
|
340
|
+
getSubscription: vi.fn(async () => ({
|
|
341
|
+
tier: SubscriptionTier.SOLO,
|
|
342
|
+
status: SubscriptionStatus.ACTIVE,
|
|
343
|
+
// ...
|
|
344
|
+
})),
|
|
345
|
+
})),
|
|
346
|
+
}));
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Troubleshooting
|
|
350
|
+
|
|
351
|
+
### "Not authenticated" Error
|
|
352
|
+
|
|
353
|
+
```bash
|
|
354
|
+
# Re-authenticate
|
|
355
|
+
praxis logout
|
|
356
|
+
praxis login
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### "Token expired" Error
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
# Refresh authentication
|
|
363
|
+
praxis login
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### "Usage limits exceeded" Error
|
|
367
|
+
|
|
368
|
+
Check your current usage:
|
|
369
|
+
|
|
370
|
+
```bash
|
|
371
|
+
praxis cloud usage
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
Upgrade your tier:
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
# Visit GitHub Sponsors
|
|
378
|
+
open https://github.com/sponsors/plures
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
## Resources
|
|
382
|
+
|
|
383
|
+
- [GitHub OAuth Documentation](https://docs.github.com/en/apps/oauth-apps)
|
|
384
|
+
- [GitHub Sponsors API](https://docs.github.com/en/graphql/reference/objects#sponsor)
|
|
385
|
+
- [GitHub Marketplace](https://docs.github.com/en/apps/github-marketplace)
|
|
386
|
+
- [Azure Blob Storage](https://docs.microsoft.com/en-us/azure/storage/blobs/)
|
|
387
|
+
|
|
388
|
+
## Support
|
|
389
|
+
|
|
390
|
+
For billing or subscription issues:
|
|
391
|
+
|
|
392
|
+
- **GitHub Sponsors**: Contact via GitHub
|
|
393
|
+
- **Enterprise**: Email enterprise@plures.dev
|
|
394
|
+
- **Community**: https://github.com/plures/praxis/discussions
|