@portaidentity/sdk 1.11.1 → 1.12.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/CHANGELOG.md CHANGED
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.12.0] - 2026-10-23
9
+
10
+ Added
11
+ - Updated documentation to clarify that /api/admin requires account-bound opaque access tokens.
12
+
13
+ Changed
14
+ - Removed client-credentials examples for Admin API automation.
15
+ - Corrected signatures for createTokenAuth and createCliAuth to adhere to the BFF pattern.
16
+
17
+ Fixed
18
+ - Updated authentication guidance in docs/api/authentication.md and several guide files to reflect accurate information.
19
+
8
20
  ## [1.11.1] - 2026-09-30
9
21
 
10
22
  Added
package/README.md CHANGED
@@ -27,16 +27,23 @@ yarn add @portaidentity/sdk
27
27
  ### Browser
28
28
 
29
29
  ```typescript
30
- import { createPortaClient, createBrowserTransport } from '@portaidentity/sdk/browser';
30
+ import { createPortaClient } from '@portaidentity/sdk';
31
+ import { createBrowserTransport } from '@portaidentity/sdk/browser';
32
+
33
+ let csrfToken: string | null = null;
31
34
 
32
35
  const transport = createBrowserTransport({
33
36
  baseUrl: '/api/admin', // BFF proxy path
34
- csrfCookieName: '_csrf', // CSRF cookie name
35
- csrfHeaderName: 'x-csrf-token',
36
- on401: () => (window.location.href = '/login'),
37
+ getCsrfToken: () => csrfToken,
38
+ setCsrfToken: (token) => {
39
+ csrfToken = token;
40
+ },
41
+ onUnauthorized: () => {
42
+ window.location.href = '/login';
43
+ },
37
44
  });
38
45
 
39
- const client = createPortaClient(transport);
46
+ const client = createPortaClient({ transport });
40
47
 
41
48
  // List organizations
42
49
  const orgs = await client.organizations.list({ page: 1, pageSize: 20 });
@@ -53,16 +60,15 @@ const user = await client.users.create({
53
60
  ### Node.js (Automation / CLI)
54
61
 
55
62
  ```typescript
56
- import { createPortaClient, createNodeTransport, createTokenAuth } from '@portaidentity/sdk/node';
57
-
58
- const auth = createTokenAuth('your-bearer-token');
63
+ import { createPortaClient } from '@portaidentity/sdk';
64
+ import { createNodeTransport, createTokenAuth } from '@portaidentity/sdk/node';
59
65
 
60
66
  const transport = createNodeTransport({
61
67
  baseUrl: 'https://porta.local:3443/api/admin',
62
- auth,
68
+ auth: createTokenAuth({ token: 'opaque-access-token' }),
63
69
  });
64
70
 
65
- const client = createPortaClient(transport);
71
+ const client = createPortaClient({ transport });
66
72
 
67
73
  // List all organizations (auto-pagination)
68
74
  const allOrgs = await client.organizations.listAll();
@@ -71,37 +77,40 @@ const allOrgs = await client.organizations.listAll();
71
77
  await client.users.deactivate('org-id', 'user-id');
72
78
 
73
79
  // Assign a role
74
- await client.userRoles.assign('org-id', 'user-id', { roleId: 'role-id' });
80
+ await client.userRoles.assign('org-id', 'user-id', ['role-id']);
75
81
  ```
76
82
 
77
- ### Client Credentials (Server-to-Server)
83
+ ### Admin API from a BFF (Server-to-Server)
84
+
85
+ The Admin API requires an opaque access token bound to an active user in the
86
+ super-admin organization with a recognized admin role. Use one of these patterns:
87
+
88
+ 1. **Dedicated control-plane user** — Authorization Code + PKCE once, then store the
89
+ refresh token in a secret manager and persist each rotation.
90
+ 2. **Short-lived token** — obtain an access token through `porta login` or the
91
+ Authorization Code flow and pass it to `createTokenAuth`.
78
92
 
79
93
  ```typescript
80
- import {
81
- createPortaClient,
82
- createNodeTransport,
83
- createClientCredentialsAuth,
84
- } from '@portaidentity/sdk/node';
85
-
86
- const auth = createClientCredentialsAuth({
87
- tokenUrl: 'https://porta.local:3443/super-admin/token',
88
- clientId: 'my-service',
89
- clientSecret: 'my-secret',
90
- scope: 'openid',
91
- });
94
+ import { createPortaClient } from '@portaidentity/sdk';
95
+ import { createNodeTransport, createTokenAuth } from '@portaidentity/sdk/node';
92
96
 
93
- const transport = createNodeTransport({
94
- baseUrl: 'https://porta.local:3443/api/admin',
95
- auth,
97
+ const client = createPortaClient({
98
+ transport: createNodeTransport({
99
+ baseUrl: 'https://porta.example.com/api/admin',
100
+ auth: createTokenAuth({ token: process.env.PORTA_ACCESS_TOKEN! }),
101
+ }),
96
102
  });
97
-
98
- const client = createPortaClient(transport);
99
103
  ```
100
104
 
105
+ Client-credentials tokens carry no account identity and are rejected by `/api/admin/*`.
106
+ Do not use `createClientCredentialsAuth` for Admin API automation until service
107
+ accounts are supported.
108
+
101
109
  ### AI Agent Integration
102
110
 
103
111
  ```typescript
104
- import { createPortaClient, getToolDefinitions, executeTool } from '@portaidentity/sdk/agent';
112
+ import { createPortaClient } from '@portaidentity/sdk';
113
+ import { getToolDefinitions, executeTool } from '@portaidentity/sdk/agent';
105
114
  import { createNodeTransport, createTokenAuth } from '@portaidentity/sdk/node';
106
115
 
107
116
  // Get tool definitions for LLM function calling
@@ -109,36 +118,39 @@ const tools = getToolDefinitions();
109
118
  // → [{ name: 'organizations.list', description: '...', parameters: [...] }, ...]
110
119
 
111
120
  // Execute a tool call from an AI agent
112
- const client = createPortaClient(
113
- createNodeTransport({ baseUrl: '...', auth: createTokenAuth('...') }),
114
- );
121
+ const client = createPortaClient({
122
+ transport: createNodeTransport({
123
+ baseUrl: 'https://porta.example.com/api/admin',
124
+ auth: createTokenAuth({ token: process.env.PORTA_ACCESS_TOKEN! }),
125
+ }),
126
+ });
115
127
 
116
128
  const result = await executeTool(client, 'organizations.list', { page: 1 });
117
129
  ```
118
130
 
119
131
  ## Domain Namespaces
120
132
 
121
- | Namespace | Methods | Description |
122
- | --------------- | ------- | ----------------------------------------------------- |
123
- | `organizations` | 10 | CRUD, status lifecycle, slug validation, history |
124
- | `applications` | 13 | CRUD, status, module management, history |
125
- | `clients` | 12 | CRUD, status, secret management, history |
126
- | `users` | 19 | CRUD, status transitions, password, email, and export |
127
- | `usersById` | 8 | Org-less get/update, password, email, and history |
128
- | `roles` | 9 | CRUD and permission assignment |
129
- | `permissions` | 6 | CRUD |
133
+ | Namespace | Methods | Description |
134
+ | --------------- | ------- | ------------------------------------------------------- |
135
+ | `organizations` | 10 | CRUD, status lifecycle, slug validation, history |
136
+ | `applications` | 13 | CRUD, status, module management, history |
137
+ | `clients` | 12 | CRUD, status, secret management, history |
138
+ | `users` | 19 | CRUD, status transitions, password, email, and export |
139
+ | `usersById` | 8 | Org-less get/update, password, email, and history |
140
+ | `roles` | 9 | CRUD and permission assignment |
141
+ | `permissions` | 6 | CRUD |
130
142
  | `userRoles` | 4 | List, assign, remove, and resolve effective permissions |
131
- | `customClaims` | 10 | Claim definition CRUD and user claim values |
132
- | `config` | 3 | System configuration get/set/list |
133
- | `keys` | 3 | Signing key list/generate/rotate |
134
- | `audit` | 1 | Audit log listing with filters |
135
- | `stats` | 1 | Dashboard statistics |
136
- | `sessions` | 3 | Session listing and revocation |
137
- | `bulk` | 1 | Bulk status operations |
138
- | `branding` | 5 | Org branding settings and asset management |
139
- | `exports` | 2 | CSV/JSON reports and selective manifest export |
140
- | `twoFactor` | 3 | 2FA status, disable, reset |
141
- | `imports` | 2 | Manifest preview and atomic import |
143
+ | `customClaims` | 10 | Claim definition CRUD and user claim values |
144
+ | `config` | 3 | System configuration get/set/list |
145
+ | `keys` | 3 | Signing key list/generate/rotate |
146
+ | `audit` | 1 | Audit log listing with filters |
147
+ | `stats` | 1 | Dashboard statistics |
148
+ | `sessions` | 3 | Session listing and revocation |
149
+ | `bulk` | 1 | Bulk status operations |
150
+ | `branding` | 5 | Org branding settings and asset management |
151
+ | `exports` | 2 | CSV/JSON reports and selective manifest export |
152
+ | `twoFactor` | 3 | 2FA status, disable, reset |
153
+ | `imports` | 2 | Manifest preview and atomic import |
142
154
 
143
155
  ## Environment Portability
144
156
 
package/dist/client.d.ts CHANGED
@@ -42,7 +42,7 @@ export interface PortaClient {
42
42
  *
43
43
  * const transport = createNodeTransport({
44
44
  * baseUrl: 'https://porta.local:3443/api/admin',
45
- * auth: createTokenAuth('my-bearer-token'),
45
+ * auth: createTokenAuth({ token: 'my-bearer-token' }),
46
46
  * });
47
47
  *
48
48
  * const porta = createPortaClient({ transport });
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAuB1D,OAAO,KAAK,EACV,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,EACb,WAAW,EACX,qBAAqB,EACrB,WAAW,EAEX,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,UAAU,EACV,WAAW,EACX,WAAW,EACX,cAAc,EACd,UAAU,EACV,cAAc,EACd,aAAa,EACb,eAAe,EACf,aAAa,EACd,MAAM,oBAAoB,CAAC;AAM5B,MAAM,WAAW,kBAAkB;IACjC,yFAAyF;IACzF,SAAS,EAAE,aAAa,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,mBAAmB,CAAC;IACnC,YAAY,EAAE,kBAAkB,CAAC;IACjC,OAAO,EAAE,aAAa,CAAC;IACvB,KAAK,EAAE,WAAW,CAAC;IACnB,kFAAkF;IAClF,SAAS,EAAE,qBAAqB,CAAC;IACjC,SAAS,EAAE,eAAe,CAAC;IAE3B,KAAK,EAAE,WAAW,CAAC;IACnB,WAAW,EAAE,iBAAiB,CAAC;IAC/B,YAAY,EAAE,kBAAkB,CAAC;IACjC,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,cAAc,CAAC;IACzB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,cAAc,CAAC;IACzB,OAAO,EAAE,aAAa,CAAC;IACvB,SAAS,EAAE,eAAe,CAAC;IAC3B,OAAO,EAAE,aAAa,CAAC;CACxB;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAyB1E"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAsB1D,OAAO,KAAK,EACV,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,EACb,WAAW,EACX,qBAAqB,EACrB,WAAW,EACX,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,UAAU,EACV,WAAW,EACX,WAAW,EACX,cAAc,EACd,UAAU,EACV,cAAc,EACd,aAAa,EACb,eAAe,EACf,aAAa,EACd,MAAM,oBAAoB,CAAC;AAM5B,MAAM,WAAW,kBAAkB;IACjC,yFAAyF;IACzF,SAAS,EAAE,aAAa,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,mBAAmB,CAAC;IACnC,YAAY,EAAE,kBAAkB,CAAC;IACjC,OAAO,EAAE,aAAa,CAAC;IACvB,KAAK,EAAE,WAAW,CAAC;IACnB,kFAAkF;IAClF,SAAS,EAAE,qBAAqB,CAAC;IACjC,SAAS,EAAE,eAAe,CAAC;IAE3B,KAAK,EAAE,WAAW,CAAC;IACnB,WAAW,EAAE,iBAAiB,CAAC;IAC/B,YAAY,EAAE,kBAAkB,CAAC;IACjC,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,cAAc,CAAC;IACzB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,cAAc,CAAC;IACzB,OAAO,EAAE,aAAa,CAAC;IACvB,SAAS,EAAE,eAAe,CAAC;IAC3B,OAAO,EAAE,aAAa,CAAC;CACxB;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAyB1E"}
package/dist/client.js CHANGED
@@ -18,7 +18,7 @@ import { createOrganizationsDomain, createApplicationsDomain, createClientsDomai
18
18
  *
19
19
  * const transport = createNodeTransport({
20
20
  * baseUrl: 'https://porta.local:3443/api/admin',
21
- * auth: createTokenAuth('my-bearer-token'),
21
+ * auth: createTokenAuth({ token: 'my-bearer-token' }),
22
22
  * });
23
23
  *
24
24
  * const porta = createPortaClient({ transport });
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,yBAAyB,EACzB,wBAAwB,EACxB,mBAAmB,EACnB,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,EAEjB,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAyD5B,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAA2B;IAC3D,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAE9B,OAAO;QACL,aAAa,EAAE,yBAAyB,CAAC,SAAS,CAAC;QACnD,YAAY,EAAE,wBAAwB,CAAC,SAAS,CAAC;QACjD,OAAO,EAAE,mBAAmB,CAAC,SAAS,CAAC;QACvC,KAAK,EAAE,iBAAiB,CAAC,SAAS,CAAC;QACnC,SAAS,EAAE,2BAA2B,CAAC,SAAS,CAAC;QACjD,SAAS,EAAE,qBAAqB,CAAC,SAAS,CAAC;QAE3C,KAAK,EAAE,iBAAiB,CAAC,SAAS,CAAC;QACnC,WAAW,EAAE,uBAAuB,CAAC,SAAS,CAAC;QAC/C,YAAY,EAAE,wBAAwB,CAAC,SAAS,CAAC;QACjD,MAAM,EAAE,kBAAkB,CAAC,SAAS,CAAC;QACrC,IAAI,EAAE,gBAAgB,CAAC,SAAS,CAAC;QACjC,KAAK,EAAE,iBAAiB,CAAC,SAAS,CAAC;QACnC,KAAK,EAAE,iBAAiB,CAAC,SAAS,CAAC;QACnC,QAAQ,EAAE,oBAAoB,CAAC,SAAS,CAAC;QACzC,IAAI,EAAE,gBAAgB,CAAC,SAAS,CAAC;QACjC,QAAQ,EAAE,oBAAoB,CAAC,SAAS,CAAC;QACzC,OAAO,EAAE,mBAAmB,CAAC,SAAS,CAAC;QACvC,SAAS,EAAE,qBAAqB,CAAC,SAAS,CAAC;QAC3C,OAAO,EAAE,mBAAmB,CAAC,SAAS,CAAC;KACxC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,yBAAyB,EACzB,wBAAwB,EACxB,mBAAmB,EACnB,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAwD5B,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAA2B;IAC3D,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAE9B,OAAO;QACL,aAAa,EAAE,yBAAyB,CAAC,SAAS,CAAC;QACnD,YAAY,EAAE,wBAAwB,CAAC,SAAS,CAAC;QACjD,OAAO,EAAE,mBAAmB,CAAC,SAAS,CAAC;QACvC,KAAK,EAAE,iBAAiB,CAAC,SAAS,CAAC;QACnC,SAAS,EAAE,2BAA2B,CAAC,SAAS,CAAC;QACjD,SAAS,EAAE,qBAAqB,CAAC,SAAS,CAAC;QAE3C,KAAK,EAAE,iBAAiB,CAAC,SAAS,CAAC;QACnC,WAAW,EAAE,uBAAuB,CAAC,SAAS,CAAC;QAC/C,YAAY,EAAE,wBAAwB,CAAC,SAAS,CAAC;QACjD,MAAM,EAAE,kBAAkB,CAAC,SAAS,CAAC;QACrC,IAAI,EAAE,gBAAgB,CAAC,SAAS,CAAC;QACjC,KAAK,EAAE,iBAAiB,CAAC,SAAS,CAAC;QACnC,KAAK,EAAE,iBAAiB,CAAC,SAAS,CAAC;QACnC,QAAQ,EAAE,oBAAoB,CAAC,SAAS,CAAC;QACzC,IAAI,EAAE,gBAAgB,CAAC,SAAS,CAAC;QACjC,QAAQ,EAAE,oBAAoB,CAAC,SAAS,CAAC;QACzC,OAAO,EAAE,mBAAmB,CAAC,SAAS,CAAC;QACvC,SAAS,EAAE,qBAAqB,CAAC,SAAS,CAAC;QAC3C,OAAO,EAAE,mBAAmB,CAAC,SAAS,CAAC;KACxC,CAAC;AACJ,CAAC"}
@@ -43,7 +43,7 @@ export interface NodeTransportOptions {
43
43
  * ```typescript
44
44
  * const transport = createNodeTransport({
45
45
  * baseUrl: 'https://porta.example.com',
46
- * auth: createTokenAuth('my-access-token'),
46
+ * auth: createTokenAuth({ token: 'my-access-token' }),
47
47
  * });
48
48
  * ```
49
49
  */
@@ -26,7 +26,7 @@ import { buildRequestUrl, extractResponseHeaders, buildCommonHeaders, serializeB
26
26
  * ```typescript
27
27
  * const transport = createNodeTransport({
28
28
  * baseUrl: 'https://porta.example.com',
29
- * auth: createTokenAuth('my-access-token'),
29
+ * auth: createTokenAuth({ token: 'my-access-token' }),
30
30
  * });
31
31
  * ```
32
32
  */
package/dist/version.d.ts CHANGED
@@ -5,5 +5,5 @@
5
5
  * allowing the server to identify SDK traffic for debugging
6
6
  * and compatibility tracking.
7
7
  */
8
- export declare const SDK_VERSION = "1.11.1";
8
+ export declare const SDK_VERSION = "1.12.0";
9
9
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -5,5 +5,5 @@
5
5
  * allowing the server to identify SDK traffic for debugging
6
6
  * and compatibility tracking.
7
7
  */
8
- export const SDK_VERSION = '1.11.1';
8
+ export const SDK_VERSION = '1.12.0';
9
9
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portaidentity/sdk",
3
- "version": "1.11.1",
3
+ "version": "1.12.0",
4
4
  "description": "Universal TypeScript SDK for the Porta Admin API",
5
5
  "type": "module",
6
6
  "exports": {