@fusebase/fusebase-gate-sdk 2.3.34-sdk.4 → 2.3.34-sdk.9

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.
@@ -11,7 +11,7 @@ export declare class AppApisApi {
11
11
  constructor(client: Client);
12
12
  /**
13
13
  * Call app API operation
14
- * Invokes a published app API operation through the owner app runtime using a runtime app token minted for the current authenticated caller context.
14
+ * Invokes a published app API operation through the owner app runtime using a runtime app token minted for the current authenticated caller context. Pass `onBehalfOfUserToken` (a platform app token, i.e. the user's `fbsfeaturetoken`) to run the call on behalf of an end user: Gate verifies it fail-closed and forwards the resolved user to the runtime as `X-Fusebase-Verified-User-Id` / `X-Fusebase-Verified-User-Source: obo`, so apps no longer need to hand-roll dual-token forwarding. The operation's `allowedCallers` / `requiredPermissions` are still evaluated against the calling identity, not the on-behalf-of user.
15
15
  */
16
16
  callAppApi(params: {
17
17
  path: {
@@ -13,7 +13,7 @@ class AppApisApi {
13
13
  }
14
14
  /**
15
15
  * Call app API operation
16
- * Invokes a published app API operation through the owner app runtime using a runtime app token minted for the current authenticated caller context.
16
+ * Invokes a published app API operation through the owner app runtime using a runtime app token minted for the current authenticated caller context. Pass `onBehalfOfUserToken` (a platform app token, i.e. the user's `fbsfeaturetoken`) to run the call on behalf of an end user: Gate verifies it fail-closed and forwards the resolved user to the runtime as `X-Fusebase-Verified-User-Id` / `X-Fusebase-Verified-User-Source: obo`, so apps no longer need to hand-roll dual-token forwarding. The operation's `allowedCallers` / `requiredPermissions` are still evaluated against the calling identity, not the on-behalf-of user.
17
17
  */
18
18
  async callAppApi(params) {
19
19
  return this.client.request({
@@ -5,7 +5,7 @@
5
5
  * Domain: org-users
6
6
  */
7
7
  import type { Client } from "../runtime/transport";
8
- import type { ClientAccountScheduledDeletionRequestContract, ClientAccountScheduledDeletionResponseContract, orgIdInPathRequired, OrgMemberRemoveResponseContract, OrgUserAddRequestContract, OrgUserAddResponseContract, OrgUserIdInPathRequired, OrgUserListResponseContract, OrgUserWorkspaceIdInPathRequired, OrgWorkspaceMemberListResponseContract, WorkspaceMemberRemoveResponseContract } from "../types";
8
+ import type { ClientAccountScheduledDeletionRequestContract, ClientAccountScheduledDeletionResponseContract, orgIdInPathRequired, OrgMemberExpectedJoinedAfterInQueryOptional, OrgMemberExpectedRoleInQueryOptional, OrgMemberRemoveResponseContract, OrgUserAddRequestContract, OrgUserAddResponseContract, OrgUserIdInPathRequired, OrgUserListResponseContract, OrgUserWorkspaceIdInPathRequired, OrgWorkspaceMemberListResponseContract, WorkspaceMemberRemoveResponseContract } from "../types";
9
9
  export declare class OrgUsersApi {
10
10
  private client;
11
11
  constructor(client: Client);
@@ -54,13 +54,17 @@ export declare class OrgUsersApi {
54
54
  }): Promise<OrgWorkspaceMemberListResponseContract>;
55
55
  /**
56
56
  * Remove organization member
57
- * Removes an organization member by numeric userId. Gate resolves the internal orgMember.globalId before calling org-service, and org-service cleans up workspace/group memberships for that org. Requires org.members.write and org access.
57
+ * Removes an organization member by numeric userId. Gate resolves the internal orgMember.globalId before calling org-service, and org-service cleans up workspace/group memberships for that org. Optional query preconditions make the removal conditional instead of unconditional: `expectedRole` requires the member to still hold that org role, and `expectedJoinedAfter` (unix seconds) requires the membership to have been created at or after that moment — use it when cancelling an invite so a pre-existing member is never dropped. Either mismatch fails with 409 and removes nothing; a precondition sent with an empty or unparsable value fails with 400 rather than degrading into an unconditional removal. Requires org.members.write and org access.
58
58
  */
59
59
  removeOrgMember(params: {
60
60
  path: {
61
61
  orgId: orgIdInPathRequired;
62
62
  userId: OrgUserIdInPathRequired;
63
63
  };
64
+ query?: {
65
+ expectedRole?: OrgMemberExpectedRoleInQueryOptional;
66
+ expectedJoinedAfter?: OrgMemberExpectedJoinedAfterInQueryOptional;
67
+ };
64
68
  headers?: Record<string, string>;
65
69
  }): Promise<OrgMemberRemoveResponseContract>;
66
70
  /**
@@ -70,13 +70,14 @@ class OrgUsersApi {
70
70
  }
71
71
  /**
72
72
  * Remove organization member
73
- * Removes an organization member by numeric userId. Gate resolves the internal orgMember.globalId before calling org-service, and org-service cleans up workspace/group memberships for that org. Requires org.members.write and org access.
73
+ * Removes an organization member by numeric userId. Gate resolves the internal orgMember.globalId before calling org-service, and org-service cleans up workspace/group memberships for that org. Optional query preconditions make the removal conditional instead of unconditional: `expectedRole` requires the member to still hold that org role, and `expectedJoinedAfter` (unix seconds) requires the membership to have been created at or after that moment — use it when cancelling an invite so a pre-existing member is never dropped. Either mismatch fails with 409 and removes nothing; a precondition sent with an empty or unparsable value fails with 400 rather than degrading into an unconditional removal. Requires org.members.write and org access.
74
74
  */
75
75
  async removeOrgMember(params) {
76
76
  return this.client.request({
77
77
  method: "DELETE",
78
78
  path: "/:orgId/users/:userId",
79
79
  pathParams: params.path,
80
+ query: params.query,
80
81
  headers: params.headers,
81
82
  opId: "removeOrgMember",
82
83
  expectedContentType: "application/json",
@@ -37,6 +37,13 @@ export interface CallAppApiRequestContract {
37
37
  path?: Record<string, string>;
38
38
  query?: Record<string, string | number | boolean>;
39
39
  body?: unknown;
40
+ /**
41
+ * On-behalf-of: a platform app token (`fbsfeaturetoken` / `x-app-feature-token`)
42
+ * identifying the end user this call runs for. Gate verifies it fail-closed and
43
+ * forwards the resolved user to the runtime as `X-Fusebase-Verified-User-*`
44
+ * headers; the calling identity still governs the operation's access policy.
45
+ */
46
+ onBehalfOfUserToken?: string;
40
47
  }
41
48
  export interface CallAppApiResponseContract {
42
49
  ok: boolean;
@@ -19,6 +19,18 @@ export interface CreateAppMagicLinkRequestContract {
19
19
  * When false, the user must already exist or the call rejects with NotFound.
20
20
  */
21
21
  addToAccessPrincipals?: boolean;
22
+ /**
23
+ * Optional link lifetime in seconds. Omit for the 24h (86400) default.
24
+ * A provided value is clamped server-side to the 3600 (1h)..604800 (7d)
25
+ * range rather than rejected, so a slightly out-of-range value still yields
26
+ * a usable link.
27
+ * `0` or a negative value is NOT "no expiry" and does NOT expire the link
28
+ * immediately — it clamps UP to the 3600 (1h) minimum, so 1h is the
29
+ * shortest lifetime you can create.
30
+ * Whole seconds: a fractional value is floored server-side.
31
+ * @TJS-type integer
32
+ */
33
+ ttlSeconds?: number;
22
34
  /**
23
35
  * Opaque app payload (not interpreted by the platform) stored on the link and
24
36
  * echoed back byte-for-byte at activation. Use it to bind the link to an
@@ -51,7 +63,8 @@ export interface CreateAppMagicLinkResponseContract {
51
63
  */
52
64
  magicLinkUrl: string;
53
65
  /**
54
- * Unix timestamp (seconds) when the link expires (createdAt + 24h).
66
+ * Unix timestamp (seconds) when the link expires (createdAt + ttlSeconds,
67
+ * defaulting to 24h when ttlSeconds is omitted).
55
68
  */
56
69
  expiresAt: number;
57
70
  }
@@ -228,6 +241,17 @@ export interface BulkAppMagicLinkInvitationContract {
228
241
  * When false, the user must already exist or the invite fails with NotFound.
229
242
  */
230
243
  addToAccessPrincipals?: boolean;
244
+ /**
245
+ * Optional link lifetime in seconds. Omit for the 24h (86400) default.
246
+ * A provided value is clamped server-side to the 3600 (1h)..604800 (7d)
247
+ * range rather than rejected.
248
+ * `0` or a negative value is NOT "no expiry" and does NOT expire the link
249
+ * immediately — it clamps UP to the 3600 (1h) minimum, so 1h is the
250
+ * shortest lifetime you can create.
251
+ * Whole seconds: a fractional value is floored server-side.
252
+ * @TJS-type integer
253
+ */
254
+ ttlSeconds?: number;
231
255
  /**
232
256
  * Opaque app payload (not interpreted by the platform) stored on the link and
233
257
  * echoed back byte-for-byte at activation.
@@ -18,7 +18,7 @@ export * from "./mcp-manager/mcp-manager";
18
18
  export type { MeAuthContract, MeOrgGroupContract, MePreferencesContract, MeResponseContract, MeScopeContract, MeUserContract } from "./me/me";
19
19
  export * from "./note/note";
20
20
  export * from "./org-group/org-group";
21
- export type { ClientAccountScheduledDeletionRequestContract, ClientAccountScheduledDeletionResponseContract, CreateWorkspaceRequestContract, OrgInviteContract, OrgMagicLinkContract, OrgMemberRemoveResponseContract, OrgPortalContract, OrgPortalListResponseContract, OrgUserAddRequestContract, OrgUserAddResponseContract, OrgUserContract, OrgUserIdInPathRequired, OrgUserListResponseContract, OrgUserWorkspaceIdInPathRequired, OrgWorkspaceContract, OrgWorkspaceInviteContract, OrgWorkspaceListResponseContract, OrgWorkspaceMemberContract, OrgWorkspaceMemberListResponseContract, WorkspaceMemberRemoveResponseContract } from "./org-user/org-user";
21
+ export type { ClientAccountScheduledDeletionRequestContract, ClientAccountScheduledDeletionResponseContract, CreateWorkspaceRequestContract, OrgInviteContract, OrgMagicLinkContract, OrgMemberExpectedJoinedAfterInQueryOptional, OrgMemberExpectedRoleInQueryOptional, OrgMemberRemoveResponseContract, OrgPortalContract, OrgPortalListResponseContract, OrgUserAddRequestContract, OrgUserAddResponseContract, OrgUserContract, OrgUserIdInPathRequired, OrgUserListResponseContract, OrgUserWorkspaceIdInPathRequired, OrgWorkspaceContract, OrgWorkspaceInviteContract, OrgWorkspaceListResponseContract, OrgWorkspaceMemberContract, OrgWorkspaceMemberListResponseContract, WorkspaceMemberRemoveResponseContract } from "./org-user/org-user";
22
22
  export * from "./orgs/orgs";
23
23
  export type { VerifyPortalFeatureContextTokenRequestContract, VerifyPortalFeatureContextTokenResponseContract } from "./portal-feature-context/portal-feature-context";
24
24
  export type { AddPortalAppPageRequestContract, AddPortalAppPageResponseContract, AddPortalBlockRequestContract, AddPortalBlockResponseContract, AddPortalNoteBlockRequestContract, AddPortalNoteBlockResponseContract, BulkInviteResultItemContract, BulkInviteToPortalRequestContract, BulkInviteToPortalResponseContract, BulkPortalInvitationContract, CreatePortalFolderRequestContract, CreatePortalFolderResponseContract, CreatePortalPageWithNoteRequestContract, CreatePortalPageWithNoteResponseContract, CreatePortalRequestContract, CreatePortalResponseContract, DuplicatePortalItemRequestContract, DuplicatePortalItemResponseContract, DuplicatePortalRequestContract, InvitePortalManagerRequestContract, InvitePortalManagerResponseContract, InviteToPortalRequestContract, InviteToPortalResponseContract, ListPortalContentResponseContract, PortalContentItemContract, PortalDetailContract, PublishPortalDraftResponseContract, UpdatePortalAccessRequestContract, UpdatePortalAccessResponseContract, UpdatePortalCustomCodeRequestContract, UpdatePortalCustomCodeResponseContract, globalIdInPathRequired } from "./portals/portals";
@@ -146,6 +146,17 @@ export interface OrgUserAddResponseContract {
146
146
  workspaceMember?: OrgWorkspaceMemberContract;
147
147
  magicLink?: OrgMagicLinkContract;
148
148
  }
149
+ /**
150
+ * Optional CAS guard for removeOrgMember: the membership is only removed when
151
+ * its current org role still equals this value.
152
+ */
153
+ export type OrgMemberExpectedRoleInQueryOptional = string;
154
+ /**
155
+ * Optional provenance guard for removeOrgMember (unix timestamp in seconds):
156
+ * the membership is only removed when it was created at or after this moment,
157
+ * so cancelling an invite can never drop a pre-existing member.
158
+ */
159
+ export type OrgMemberExpectedJoinedAfterInQueryOptional = number;
149
160
  export interface OrgMemberRemoveResponseContract {
150
161
  ok: true;
151
162
  userId: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusebase/fusebase-gate-sdk",
3
- "version": "2.3.34-sdk.4",
3
+ "version": "2.3.34-sdk.9",
4
4
  "description": "TypeScript SDK for Fusebase Gate APIs - Generated from contract introspection",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -0,0 +1,9 @@
1
+ # Release Notes 2.3.34-sdk.9
2
+
3
+ - Current ref: `HEAD`
4
+ - Previous tag: `v2.3.34-sdk.9`
5
+ - Generated at: 2026-07-23T15:54:33.520Z
6
+
7
+ ## Included Drafts
8
+
9
+ - None
@@ -1,82 +1,9 @@
1
- # Release Notes 2.3.34-sdk.4
1
+ # Release Notes 2.3.34-sdk.9
2
2
 
3
3
  - Current ref: `HEAD`
4
- - Previous tag: `v2.3.28-sdk.3`
5
- - Generated at: 2026-07-23T05:48:58.238Z
4
+ - Previous tag: `v2.3.34-sdk.9`
5
+ - Generated at: 2026-07-23T15:54:33.520Z
6
6
 
7
7
  ## Included Drafts
8
8
 
9
- - `docs/release-notes/2026-07-02-markdown-notes-crud.md` - Markdown (v3) notes CRUD
10
- - `docs/release-notes/2026-07-13-getme-no-health-read.md` - getMe no longer requires health.read
11
-
12
- ## Summary
13
-
14
- ### Markdown (v3) notes CRUD
15
-
16
- Add Gate contracts, controllers, and MCP-visible operations for v3 markdown notes: create, read, replace, and append markdown stored as the source of truth in note-service (no editor-service involved). Part of Notes v3 Iteration 1 (NIM-42034, NIM-42042).
17
-
18
- ### getMe no longer requires health.read
19
-
20
- `GET /me` (`getMe`) no longer declares a required Gate permission. Any authenticated **user** or **token** subject may call it with a valid session, without `health.read` in the grant.
21
-
22
-
23
- ## API / SDK Changes
24
-
25
- ### Markdown (v3) notes CRUD
26
-
27
- - Added `createWorkspaceMarkdownNote` (`POST /:orgId/workspaces/:workspaceId/markdown-notes`).
28
- - Added `getWorkspaceMarkdownNote` (`GET .../markdown-notes/:noteId`) returning the markdown source of truth plus `revision`.
29
- - Added `updateWorkspaceMarkdownNoteContent` (`PUT .../markdown-notes/:noteId/content`) replacing the full markdown document with a required optimistic `revision` lock.
30
- - Added `appendWorkspaceMarkdownNoteContent` (`POST .../markdown-notes/:noteId/content/append`) with an optional `revision` lock.
31
- - Stale-revision writes return HTTP 409 with `data.errorCode = markdown_note_revision_conflict` and `data.currentRevision`.
32
- - Regenerated SDK/OpenAPI artifacts include the new Notes API methods and contracts.
33
-
34
-
35
- ## Consumer Impact
36
-
37
- ### Markdown (v3) notes CRUD
38
-
39
- AI/MCP callers can manage markdown-native (v3) notes end-to-end without HTML conversion. Classic (v2) notes are untouched and keep using the existing notes operations. The operations depend on the note-service markdown API (NIM-42040/NIM-42041); until note-service ships it, calls fail upstream.
40
-
41
-
42
- ## Verification
43
-
44
- ### Markdown (v3) notes CRUD
45
-
46
- - `npm run build`
47
- - `npm run build:sdk`
48
- - `npm run mcp:skills:generate`
49
- - `npm run mcp:skills:validate`
50
- - `npm test` (unit suites for the new controller, client, and contracts)
51
-
52
- ### getMe no longer requires health.read
53
-
54
- - `npm run test:unit -- tests/unit/authz-op-registry-bridge.test.ts`
55
- - `npm run build`
56
-
57
-
58
- ## Follow-ups
59
-
60
- ### Markdown (v3) notes CRUD
61
-
62
- - Switch the plain-HTTP note-service markdown client to the generated `@internal/note-service` SDK once note-service publishes the markdown endpoints.
63
- - Add e2e-sdk/mcp-e2e coverage once the note-service contract is live (fake-note-service markdown routes should mirror the real service).
64
-
65
-
66
- ## Consumer impact
67
-
68
- ### getMe no longer requires health.read
69
-
70
- - **Apps without `health.read` in the published grant** can call `getMe` again (service tokens, visitor browser tokens).
71
- - **Apps that already include `health.read`** are unchanged.
72
- - Do **not** remove `health.read` from grants solely because of this change — other ops may still require it.
73
- - Continue using `FBS_ORG_ID` / `getMyOrgAccess` for org resolution; do not rely on `getMe().auth.scopes` for visitor sessions.
74
-
75
-
76
- ## Why
77
-
78
- ### getMe no longer requires health.read
79
-
80
- - `getMe` is the primary identity introspection op for Fusebase Apps.
81
- - Requiring `health.read` caused production lockouts when app grants omitted it after `fusebase analyze gate` / `--sync-gate-permissions` (see issue `041-benchmarking-app`, escalation `2026-07-13-platform-gate-2.3.29-auth-breaking-changes.md`).
82
- - `resolveOperationPermissions` now reports `required_permission: null` for `getMe`, aligned with `getHealth`.
9
+ - None
@@ -1,9 +0,0 @@
1
- # Release Notes 2.3.34-sdk.3
2
-
3
- - Current ref: `HEAD`
4
- - Previous tag: `v2.3.34-sdk.2`
5
- - Generated at: 2026-07-21T14:24:27.829Z
6
-
7
- ## Included Drafts
8
-
9
- - None
@@ -1,82 +0,0 @@
1
- # Release Notes 2.3.34-sdk.4
2
-
3
- - Current ref: `HEAD`
4
- - Previous tag: `v2.3.28-sdk.3`
5
- - Generated at: 2026-07-23T05:48:58.238Z
6
-
7
- ## Included Drafts
8
-
9
- - `docs/release-notes/2026-07-02-markdown-notes-crud.md` - Markdown (v3) notes CRUD
10
- - `docs/release-notes/2026-07-13-getme-no-health-read.md` - getMe no longer requires health.read
11
-
12
- ## Summary
13
-
14
- ### Markdown (v3) notes CRUD
15
-
16
- Add Gate contracts, controllers, and MCP-visible operations for v3 markdown notes: create, read, replace, and append markdown stored as the source of truth in note-service (no editor-service involved). Part of Notes v3 Iteration 1 (NIM-42034, NIM-42042).
17
-
18
- ### getMe no longer requires health.read
19
-
20
- `GET /me` (`getMe`) no longer declares a required Gate permission. Any authenticated **user** or **token** subject may call it with a valid session, without `health.read` in the grant.
21
-
22
-
23
- ## API / SDK Changes
24
-
25
- ### Markdown (v3) notes CRUD
26
-
27
- - Added `createWorkspaceMarkdownNote` (`POST /:orgId/workspaces/:workspaceId/markdown-notes`).
28
- - Added `getWorkspaceMarkdownNote` (`GET .../markdown-notes/:noteId`) returning the markdown source of truth plus `revision`.
29
- - Added `updateWorkspaceMarkdownNoteContent` (`PUT .../markdown-notes/:noteId/content`) replacing the full markdown document with a required optimistic `revision` lock.
30
- - Added `appendWorkspaceMarkdownNoteContent` (`POST .../markdown-notes/:noteId/content/append`) with an optional `revision` lock.
31
- - Stale-revision writes return HTTP 409 with `data.errorCode = markdown_note_revision_conflict` and `data.currentRevision`.
32
- - Regenerated SDK/OpenAPI artifacts include the new Notes API methods and contracts.
33
-
34
-
35
- ## Consumer Impact
36
-
37
- ### Markdown (v3) notes CRUD
38
-
39
- AI/MCP callers can manage markdown-native (v3) notes end-to-end without HTML conversion. Classic (v2) notes are untouched and keep using the existing notes operations. The operations depend on the note-service markdown API (NIM-42040/NIM-42041); until note-service ships it, calls fail upstream.
40
-
41
-
42
- ## Verification
43
-
44
- ### Markdown (v3) notes CRUD
45
-
46
- - `npm run build`
47
- - `npm run build:sdk`
48
- - `npm run mcp:skills:generate`
49
- - `npm run mcp:skills:validate`
50
- - `npm test` (unit suites for the new controller, client, and contracts)
51
-
52
- ### getMe no longer requires health.read
53
-
54
- - `npm run test:unit -- tests/unit/authz-op-registry-bridge.test.ts`
55
- - `npm run build`
56
-
57
-
58
- ## Follow-ups
59
-
60
- ### Markdown (v3) notes CRUD
61
-
62
- - Switch the plain-HTTP note-service markdown client to the generated `@internal/note-service` SDK once note-service publishes the markdown endpoints.
63
- - Add e2e-sdk/mcp-e2e coverage once the note-service contract is live (fake-note-service markdown routes should mirror the real service).
64
-
65
-
66
- ## Consumer impact
67
-
68
- ### getMe no longer requires health.read
69
-
70
- - **Apps without `health.read` in the published grant** can call `getMe` again (service tokens, visitor browser tokens).
71
- - **Apps that already include `health.read`** are unchanged.
72
- - Do **not** remove `health.read` from grants solely because of this change — other ops may still require it.
73
- - Continue using `FBS_ORG_ID` / `getMyOrgAccess` for org resolution; do not rely on `getMe().auth.scopes` for visitor sessions.
74
-
75
-
76
- ## Why
77
-
78
- ### getMe no longer requires health.read
79
-
80
- - `getMe` is the primary identity introspection op for Fusebase Apps.
81
- - Requiring `health.read` caused production lockouts when app grants omitted it after `fusebase analyze gate` / `--sync-gate-permissions` (see issue `041-benchmarking-app`, escalation `2026-07-13-platform-gate-2.3.29-auth-breaking-changes.md`).
82
- - `resolveOperationPermissions` now reports `required_permission: null` for `getMe`, aligned with `getHealth`.