@productcraft/platform-auth 0.0.2 → 0.0.4

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/README.md ADDED
@@ -0,0 +1,219 @@
1
+ # @productcraft/platform-auth
2
+
3
+ Typed Node.js SDK for [ProductCraft Platform-Auth](https://productcraft.co) — PlatformUser sign-in / sign-up / password reset, workspaces, members + invites, workspace roles + IAM policies, workspace API keys, service activation, and the `/v1/introspect` endpoint every other ProductCraft backend uses to resolve permissions.
4
+
5
+ ```bash
6
+ npm install @productcraft/platform-auth
7
+ ```
8
+
9
+ Server-side only. The SDK ships a Platform API Key in the `Authorization` header — never embed it in a browser bundle.
10
+
11
+ ## Which SDK do I want?
12
+
13
+ | If your goal is to … | Reach for |
14
+ |---|---|
15
+ | Authenticate **your own end-users** in a product you're building (Heimdall apps) | [`@productcraft/heimdall`](https://www.npmjs.com/package/@productcraft/heimdall) |
16
+ | Authenticate **your team** into the ProductCraft console + manage workspaces | **this package** |
17
+
18
+ The two are easy to confuse because both have "auth" in the name. Platform-Auth owns *the ProductCraft account you use to log into productcraft.co*. Heimdall owns *the end-users of products you build on the platform*. Distinct databases, distinct signing keys.
19
+
20
+ ## Quick start
21
+
22
+ ```ts
23
+ import { PlatformAuth } from "@productcraft/platform-auth";
24
+
25
+ const platformAuth = new PlatformAuth({
26
+ auth: { type: "apiKey", key: process.env.PCFT_KEY! },
27
+ });
28
+
29
+ // Resolve the caller's effective policy + enabled services for a workspace
30
+ const { data } = await platformAuth.client.GET(
31
+ "/v1/introspect/workspaces/{workspace_id}",
32
+ { params: { path: { workspace_id: "ws_..." } } },
33
+ );
34
+
35
+ // data.policy.statements[…] — what the caller is allowed to do
36
+ // data.enabled_services[…] — envoi / rally / agora / heimdall / …
37
+ ```
38
+
39
+ The `client` is an [`openapi-fetch`](https://openapi-ts.dev/openapi-fetch/) instance bound to `https://api.auth.productcraft.co` and your auth credential.
40
+
41
+ ## Configuration
42
+
43
+ ```ts
44
+ new PlatformAuth({
45
+ auth: { type: "apiKey", key: "pcft_live_..." }
46
+ | { type: "bearer", token: "eyJ..." }
47
+ | { type: "cookie", value: "auth_token=..." },
48
+ baseUrl: "https://api.auth.example.test", // optional override
49
+ fetch: customFetch, // optional
50
+ });
51
+ ```
52
+
53
+ ## Common operations
54
+
55
+ ### Authentication (PlatformUser sign-in)
56
+
57
+ ```ts
58
+ // Sign in
59
+ await platformAuth.client.POST(
60
+ "/v1/auth/signin",
61
+ { body: { identifier: "you@example.com", password: "..." } },
62
+ );
63
+
64
+ // Refresh tokens
65
+ await platformAuth.client.POST("/v1/auth/refresh", { body: { refresh_token } });
66
+
67
+ // Logout (single session) — or /v1/auth/logout to revoke every refresh token
68
+ await platformAuth.client.POST("/v1/auth/logout-current", { body: { refresh_token } });
69
+
70
+ // Password reset
71
+ await platformAuth.client.POST(
72
+ "/v1/auth/password/request-reset",
73
+ { body: { email: "you@example.com" } },
74
+ );
75
+
76
+ await platformAuth.client.POST(
77
+ "/v1/auth/password/reset",
78
+ { body: { token, new_password: "..." } },
79
+ );
80
+ ```
81
+
82
+ ### Introspect — used by every other ProductCraft backend
83
+
84
+ ```ts
85
+ // Resolve the bearer of a token: returns account + email_verified_at + workspaces
86
+ await platformAuth.client.GET("/v1/introspect");
87
+
88
+ // Resolve effective policy + enabled services for one workspace
89
+ await platformAuth.client.GET(
90
+ "/v1/introspect/workspaces/{workspace_id}",
91
+ { params: { path: { workspace_id: "ws_..." } } },
92
+ );
93
+
94
+ // Resolve a PAK — used internally by services that accept pcft_live_* on routes
95
+ await platformAuth.client.GET("/v1/introspect/api-key");
96
+ ```
97
+
98
+ The latter two are cached by every consuming service for ~60 seconds. Reach for them from a backend gate; never from a hot request path.
99
+
100
+ ### Workspaces
101
+
102
+ ```ts
103
+ // List
104
+ await platformAuth.client.GET("/v1/workspaces");
105
+
106
+ // Create
107
+ await platformAuth.client.POST(
108
+ "/v1/workspaces",
109
+ { body: { name: "Acme", slug: "acme" } },
110
+ );
111
+
112
+ // Get / update / delete by slug
113
+ await platformAuth.client.GET("/v1/workspaces/{workspace_slug}", { ... });
114
+ ```
115
+
116
+ ### Members, invites, roles
117
+
118
+ ```ts
119
+ // Members
120
+ await platformAuth.client.GET("/v1/workspaces/{workspace_slug}/members", { ... });
121
+ await platformAuth.client.PATCH(
122
+ "/v1/workspaces/{workspace_slug}/members/{account_id}/role",
123
+ { params: { ... }, body: { role_id: "role_..." } },
124
+ );
125
+
126
+ // Invites
127
+ await platformAuth.client.POST(
128
+ "/v1/workspaces/{workspace_slug}/invites",
129
+ { params: { ... }, body: { email: "...", role_id: "..." } },
130
+ );
131
+ await platformAuth.client.POST("/v1/workspaces/invites/accept", { body: { code } });
132
+
133
+ // Roles
134
+ await platformAuth.client.POST(
135
+ "/v1/workspaces/{workspace_slug}/roles",
136
+ { params: { ... }, body: { name: "billing-admin", policy_ids: ["pol_..."] } },
137
+ );
138
+ ```
139
+
140
+ ### IAM policies
141
+
142
+ ```ts
143
+ // List the canonical permission catalogue (what verbs exist for each service)
144
+ await platformAuth.client.GET(
145
+ "/v1/workspaces/{workspace_slug}/policies/actions/catalog",
146
+ { ... },
147
+ );
148
+
149
+ // Create a custom policy
150
+ await platformAuth.client.POST(
151
+ "/v1/workspaces/{workspace_slug}/policies",
152
+ {
153
+ params: { ... },
154
+ body: {
155
+ name: "Envoi-read-only",
156
+ statements: [
157
+ { effect: "allow", actions: ["envoi.read", "envoi.list"], resources: ["*"] },
158
+ ],
159
+ },
160
+ },
161
+ );
162
+ ```
163
+
164
+ ### Workspace API keys (PATs)
165
+
166
+ ```ts
167
+ // Mint a PAK for CI / IaC
168
+ await platformAuth.client.POST(
169
+ "/v1/workspaces/{workspace_slug}/api-keys",
170
+ { params: { ... }, body: { name: "github-actions", policy_ids: ["pol_..."] } },
171
+ );
172
+
173
+ // Bind / unbind a PAK to additional workspaces (rare — most PAKs stay
174
+ // scoped to the workspace they were minted under)
175
+ await platformAuth.client.PUT(
176
+ "/v1/workspaces/{workspace_slug}/api-keys/{id}/bindings",
177
+ { ... },
178
+ );
179
+ ```
180
+
181
+ ### Service activation
182
+
183
+ ```ts
184
+ // Enable / disable a service for the workspace (envoi, rally, agora, heimdall, …)
185
+ await platformAuth.client.PUT(
186
+ "/v1/workspaces/{workspace_slug}/services/{service}",
187
+ { params: { ... }, body: { enabled: true } },
188
+ );
189
+
190
+ // Per-service workspace settings
191
+ await platformAuth.client.PUT(
192
+ "/v1/workspaces/{workspace_slug}/services/{service}/settings",
193
+ { ... },
194
+ );
195
+ ```
196
+
197
+ ### Audit
198
+
199
+ ```ts
200
+ // Read the workspace audit log
201
+ await platformAuth.client.GET(
202
+ "/v1/workspaces/{workspace_slug}/audit-logs",
203
+ { params: { ... }, query: { limit: 100 } },
204
+ );
205
+
206
+ // Streaming-friendly "recent activity" feed (for the console UI)
207
+ await platformAuth.client.GET(
208
+ "/v1/workspaces/{workspace_slug}/audit-feed",
209
+ { ... },
210
+ );
211
+ ```
212
+
213
+ ## How this SDK is built
214
+
215
+ Generated from the live OpenAPI spec at `https://api.auth.productcraft.co/docs-json` via [`openapi-typescript`](https://openapi-ts.dev/) + [`openapi-fetch`](https://openapi-ts.dev/openapi-fetch/). The nightly `spec-refresh` workflow opens a PR whenever the spec changes.
216
+
217
+ ## License
218
+
219
+ [MIT](https://github.com/clauderanelagh/productcraft-node/blob/main/LICENSE).