@productcraft/platform-auth 0.0.4 → 0.0.5
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 +69 -21
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -29,15 +29,25 @@ const platformAuth = new PlatformAuth({
|
|
|
29
29
|
// Resolve the caller's effective policy + enabled services for a workspace
|
|
30
30
|
const { data } = await platformAuth.client.GET(
|
|
31
31
|
"/v1/introspect/workspaces/{workspace_id}",
|
|
32
|
-
{ params: { path: { workspace_id: "
|
|
32
|
+
{ params: { path: { workspace_id: "<workspace-uuid>" } } },
|
|
33
33
|
);
|
|
34
34
|
|
|
35
|
-
// data.policy
|
|
36
|
-
// data.
|
|
35
|
+
// data.policy — flat array of IAM-style { effect, actions, resources } statements
|
|
36
|
+
// data.services — string[] of enabled services (envoi / rally / agora / heimdall / …)
|
|
37
37
|
```
|
|
38
38
|
|
|
39
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
40
|
|
|
41
|
+
### Auth modes
|
|
42
|
+
|
|
43
|
+
| Mode | When to use | Mint/rotate/delete surfaces |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| `apiKey` (`pcft_live_*`) | Backend-to-backend reads + introspect calls | ❌ — mint requires a human session |
|
|
46
|
+
| `bearer` (PlatformUser JWT) | Anything administrative: workspace create/delete, role/policy authoring, PAK minting, invite mutations | ✅ |
|
|
47
|
+
| `cookie` (`auth_token`) | Server-side route handlers running behind the console session | ✅ |
|
|
48
|
+
|
|
49
|
+
PAKs are workspace-scoped credentials — they read + introspect freely against the workspace they're bound to but cannot mint another PAK or reshape the human-admin surface. Cross-workspace probes by a PAK return the uniform non-member shape (no slug → UUID oracle).
|
|
50
|
+
|
|
41
51
|
## Configuration
|
|
42
52
|
|
|
43
53
|
```ts
|
|
@@ -82,17 +92,21 @@ await platformAuth.client.POST(
|
|
|
82
92
|
### Introspect — used by every other ProductCraft backend
|
|
83
93
|
|
|
84
94
|
```ts
|
|
85
|
-
// Resolve the bearer of a token: returns account + email_verified_at + workspaces
|
|
95
|
+
// Resolve the bearer of a token: returns account + email_verified_at + workspaces.
|
|
96
|
+
// Accepts a `pcft_live_*` PAK too — the response carries a synthetic verified
|
|
97
|
+
// account block so downstream `RequireEmailVerifiedGuard`-style gates pass.
|
|
86
98
|
await platformAuth.client.GET("/v1/introspect");
|
|
87
99
|
|
|
88
100
|
// Resolve effective policy + enabled services for one workspace
|
|
89
101
|
await platformAuth.client.GET(
|
|
90
102
|
"/v1/introspect/workspaces/{workspace_id}",
|
|
91
|
-
{ params: { path: { workspace_id: "
|
|
103
|
+
{ params: { path: { workspace_id: "<workspace-uuid>" } } },
|
|
92
104
|
);
|
|
93
105
|
|
|
94
|
-
// Resolve a PAK —
|
|
95
|
-
|
|
106
|
+
// Resolve a PAK — POST, not GET. Used internally by services that accept
|
|
107
|
+
// `pcft_live_*` on routes. Caller's bearer is the PAK being introspected;
|
|
108
|
+
// the body is unused (sent as `{}`).
|
|
109
|
+
await platformAuth.client.POST("/v1/introspect/api-key");
|
|
96
110
|
```
|
|
97
111
|
|
|
98
112
|
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.
|
|
@@ -100,17 +114,21 @@ The latter two are cached by every consuming service for ~60 seconds. Reach for
|
|
|
100
114
|
### Workspaces
|
|
101
115
|
|
|
102
116
|
```ts
|
|
103
|
-
// List
|
|
117
|
+
// List — for a PAK caller, this returns exactly the workspace the PAK is
|
|
118
|
+
// bound to (member_role / member_role_id are null on that lane).
|
|
104
119
|
await platformAuth.client.GET("/v1/workspaces");
|
|
105
120
|
|
|
106
|
-
// Create
|
|
121
|
+
// Create — cookie/JWT only. PAKs cannot create workspaces.
|
|
107
122
|
await platformAuth.client.POST(
|
|
108
123
|
"/v1/workspaces",
|
|
109
|
-
{ body: {
|
|
124
|
+
{ body: { display_name: "Acme", slug: "acme" } },
|
|
110
125
|
);
|
|
111
126
|
|
|
112
|
-
// Get / update
|
|
127
|
+
// Get / update by slug
|
|
113
128
|
await platformAuth.client.GET("/v1/workspaces/{workspace_slug}", { ... });
|
|
129
|
+
|
|
130
|
+
// Delete — cookie/JWT only. PAKs cannot delete workspaces.
|
|
131
|
+
await platformAuth.client.DELETE("/v1/workspaces/{workspace_slug}", { ... });
|
|
114
132
|
```
|
|
115
133
|
|
|
116
134
|
### Members, invites, roles
|
|
@@ -146,14 +164,15 @@ await platformAuth.client.GET(
|
|
|
146
164
|
{ ... },
|
|
147
165
|
);
|
|
148
166
|
|
|
149
|
-
// Create a
|
|
167
|
+
// Create a managed policy. Cookie/JWT only.
|
|
150
168
|
await platformAuth.client.POST(
|
|
151
169
|
"/v1/workspaces/{workspace_slug}/policies",
|
|
152
170
|
{
|
|
153
171
|
params: { ... },
|
|
154
172
|
body: {
|
|
155
|
-
name: "
|
|
156
|
-
|
|
173
|
+
name: "envoi-read-only",
|
|
174
|
+
description: "Read-only access to all Envoi resources",
|
|
175
|
+
policy: [
|
|
157
176
|
{ effect: "allow", actions: ["envoi.read", "envoi.list"], resources: ["*"] },
|
|
158
177
|
],
|
|
159
178
|
},
|
|
@@ -163,18 +182,47 @@ await platformAuth.client.POST(
|
|
|
163
182
|
|
|
164
183
|
### Workspace API keys (PATs)
|
|
165
184
|
|
|
185
|
+
PATs bind to one or more managed `workspace_policy` rows. Author the policy first, then mint the key with its id. The inline `policy: [...]` shape is **not** accepted — `policy_ids: [<uuid>]` is required.
|
|
186
|
+
|
|
187
|
+
Mint / rotate / revoke require a cookie or JWT — a PAK cannot mint another PAK.
|
|
188
|
+
|
|
166
189
|
```ts
|
|
167
|
-
//
|
|
168
|
-
await platformAuth.client.POST(
|
|
190
|
+
// 1. Author (or reuse) a managed policy
|
|
191
|
+
const { data: policy } = await platformAuth.client.POST(
|
|
192
|
+
"/v1/workspaces/{workspace_slug}/policies",
|
|
193
|
+
{
|
|
194
|
+
params: { path: { workspace_slug: "acme" } },
|
|
195
|
+
body: {
|
|
196
|
+
name: "ci-staging-deploy",
|
|
197
|
+
description: "Heimdall + Envoi for the staging pipeline",
|
|
198
|
+
policy: [
|
|
199
|
+
{ effect: "allow", actions: ["heimdall.create", "heimdall.read", "heimdall.update"], resources: ["pcft:heimdall:app/*"] },
|
|
200
|
+
{ effect: "allow", actions: ["envoi.template.read", "envoi.template.send"], resources: ["*"] },
|
|
201
|
+
],
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
// 2. Mint a PAT that binds to that policy
|
|
207
|
+
const { data: pak } = await platformAuth.client.POST(
|
|
169
208
|
"/v1/workspaces/{workspace_slug}/api-keys",
|
|
170
|
-
{
|
|
209
|
+
{
|
|
210
|
+
params: { path: { workspace_slug: "acme" } },
|
|
211
|
+
body: {
|
|
212
|
+
name: "github-actions-staging-deploy",
|
|
213
|
+
description: "Deploys acme-staging app from CI",
|
|
214
|
+
policy_ids: [policy!.id],
|
|
215
|
+
},
|
|
216
|
+
},
|
|
171
217
|
);
|
|
218
|
+
// pak.token — the plaintext `pcft_live_*` value, returned exactly once
|
|
219
|
+
// pak.record — public metadata (id, prefix, policies, last_used_at, …)
|
|
172
220
|
|
|
173
|
-
//
|
|
174
|
-
//
|
|
175
|
-
await platformAuth.client.
|
|
221
|
+
// Replace the bound policies on an existing PAK (re-runs caller-narrowing
|
|
222
|
+
// against the merged statement set)
|
|
223
|
+
await platformAuth.client.PATCH(
|
|
176
224
|
"/v1/workspaces/{workspace_slug}/api-keys/{id}/bindings",
|
|
177
|
-
{ ... },
|
|
225
|
+
{ params: { ... }, body: { policy_ids: ["<new-policy-uuid>"] } },
|
|
178
226
|
);
|
|
179
227
|
```
|
|
180
228
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@productcraft/platform-auth",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "PlatformUser auth, workspaces, members, invites, roles + IAM policies, API keys, service activation, and the introspect endpoint every ProductCraft backend uses to resolve permissions. Generated from the production OpenAPI spec.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|