@fusebase/fusebase-gate-sdk 2.2.15-sdk.6 → 2.2.15

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 user.
14
+ * Invokes a published app API operation through the owner app runtime using a runtime app token minted for the current authenticated caller context.
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 user.
16
+ * Invokes a published app API operation through the owner app runtime using a runtime app token minted for the current authenticated caller context.
17
17
  */
18
18
  async callAppApi(params) {
19
19
  return this.client.request({
@@ -5,7 +5,7 @@
5
5
  * Domain: isolated-stores
6
6
  */
7
7
  import type { Client } from "../runtime/transport";
8
- import type { AdoptIsolatedStoreSqlMigrationBaselineRequestContract, AdoptIsolatedStoreSqlMigrationBaselineResponseContract, ApplyIsolatedStoreSqlMigrationsRequestContract, ApplyIsolatedStoreSqlMigrationsResponseContract, CreateIsolatedStoreCheckpointRequestContract, CreateIsolatedStoreCheckpointResponseContract, CreateIsolatedStoreRequestContract, CreateIsolatedStoreResponseContract, DeleteIsolatedStoreResponseContract, DeleteIsolatedStoreStageResponseContract, GetIsolatedStoreSqlMigrationStatusRequestContract, GetOrCreateIsolatedStoreRequestContract, GetOrCreateIsolatedStoreResponseContract, InitIsolatedStoreStageRequestContract, InitIsolatedStoreStageResponseContract, IsolatedStoreIdInPathRequired, IsolatedStoreListResponseContract, IsolatedStoreResponseContract, IsolatedStoreRevisionIdInPathRequired, IsolatedStoreRevisionListResponseContract, IsolatedStoreSqlBatchInsertRequestContract, IsolatedStoreSqlBatchInsertResponseContract, IsolatedStoreSqlCountRequestContract, IsolatedStoreSqlCountResponseContract, IsolatedStoreSqlDeleteRequestContract, IsolatedStoreSqlDeleteResponseContract, IsolatedStoreSqlDescribeTableResponseContract, IsolatedStoreSqlExecuteRequestContract, IsolatedStoreSqlExecuteResponseContract, IsolatedStoreSqlImportRequestContract, IsolatedStoreSqlImportResponseContract, IsolatedStoreSqlInsertRequestContract, IsolatedStoreSqlInsertResponseContract, IsolatedStoreSqlListTablesResponseContract, IsolatedStoreSqlMigrationStatusContract, IsolatedStoreSqlQueryRequestContract, IsolatedStoreSqlQueryResponseContract, IsolatedStoreSqlSchemaNameInQueryOptional, IsolatedStoreSqlSelectRequestContract, IsolatedStoreSqlSelectResponseContract, IsolatedStoreSqlStatsResponseContract, IsolatedStoreSqlTableNameInPathRequired, IsolatedStoreSqlUpdateRequestContract, IsolatedStoreSqlUpdateResponseContract, IsolatedStoreStageInPathRequired, IsolatedStoreStageListResponseContract, ListIsolatedStoresAliasLikeInQueryOptional, ListIsolatedStoresClientIdInQueryOptional, orgIdInPathRequired, RepairIsolatedStoreSqlMigrationJournalChecksumsRequestContract, RepairIsolatedStoreSqlMigrationJournalChecksumsResponseContract, RestoreIsolatedStoreRevisionResponseContract } from "../types";
8
+ import type { AdoptIsolatedStoreSqlMigrationBaselineRequestContract, AdoptIsolatedStoreSqlMigrationBaselineResponseContract, ApplyIsolatedStoreSqlMigrationsRequestContract, ApplyIsolatedStoreSqlMigrationsResponseContract, AttachIsolatedStoreSourceScopeRequestContract, AttachIsolatedStoreSourceScopeResponseContract, CreateIsolatedStoreCheckpointRequestContract, CreateIsolatedStoreCheckpointResponseContract, CreateIsolatedStoreRequestContract, CreateIsolatedStoreResponseContract, DeleteIsolatedStoreResponseContract, DeleteIsolatedStoreStageResponseContract, GetIsolatedStoreSqlMigrationStatusRequestContract, GetOrCreateIsolatedStoreRequestContract, GetOrCreateIsolatedStoreResponseContract, InitIsolatedStoreStageRequestContract, InitIsolatedStoreStageResponseContract, IsolatedStoreIdInPathRequired, IsolatedStoreListResponseContract, IsolatedStoreResponseContract, IsolatedStoreRevisionIdInPathRequired, IsolatedStoreRevisionListResponseContract, IsolatedStoreSqlBatchInsertRequestContract, IsolatedStoreSqlBatchInsertResponseContract, IsolatedStoreSqlCountRequestContract, IsolatedStoreSqlCountResponseContract, IsolatedStoreSqlDeleteRequestContract, IsolatedStoreSqlDeleteResponseContract, IsolatedStoreSqlDescribeTableResponseContract, IsolatedStoreSqlExecuteRequestContract, IsolatedStoreSqlExecuteResponseContract, IsolatedStoreSqlImportRequestContract, IsolatedStoreSqlImportResponseContract, IsolatedStoreSqlInsertRequestContract, IsolatedStoreSqlInsertResponseContract, IsolatedStoreSqlListTablesResponseContract, IsolatedStoreSqlMigrationStatusContract, IsolatedStoreSqlQueryRequestContract, IsolatedStoreSqlQueryResponseContract, IsolatedStoreSqlSchemaNameInQueryOptional, IsolatedStoreSqlSelectRequestContract, IsolatedStoreSqlSelectResponseContract, IsolatedStoreSqlStatsResponseContract, IsolatedStoreSqlTableNameInPathRequired, IsolatedStoreSqlUpdateRequestContract, IsolatedStoreSqlUpdateResponseContract, IsolatedStoreStageInPathRequired, IsolatedStoreStageListResponseContract, ListIsolatedStoresAliasLikeInQueryOptional, ListIsolatedStoresClientIdInQueryOptional, orgIdInPathRequired, RepairIsolatedStoreSqlMigrationJournalChecksumsRequestContract, RepairIsolatedStoreSqlMigrationJournalChecksumsResponseContract, RestoreIsolatedStoreRevisionResponseContract } from "../types";
9
9
  export declare class IsolatedStoresApi {
10
10
  private client;
11
11
  constructor(client: Client);
@@ -35,6 +35,18 @@ export declare class IsolatedStoresApi {
35
35
  headers?: Record<string, string>;
36
36
  body: ApplyIsolatedStoreSqlMigrationsRequestContract;
37
37
  }): Promise<ApplyIsolatedStoreSqlMigrationsResponseContract>;
38
+ /**
39
+ * Attach isolated store source scope
40
+ * Non-destructively grants an additional app source binding to an existing isolated store without changing stages or data. Useful when a store was originally created under an older app id but runtime app tokens need access.
41
+ */
42
+ attachIsolatedStoreSourceScope(params: {
43
+ path: {
44
+ orgId: orgIdInPathRequired;
45
+ storeId: IsolatedStoreIdInPathRequired;
46
+ };
47
+ headers?: Record<string, string>;
48
+ body: AttachIsolatedStoreSourceScopeRequestContract;
49
+ }): Promise<AttachIsolatedStoreSourceScopeResponseContract>;
38
50
  /**
39
51
  * Batch insert rows
40
52
  * Inserts multiple rows into a postgres table with a shared column set. Row cap per request is floor(65535 / columnCount) (Postgres bind-parameter limit). For very large loads use importIsolatedStoreSqlRows (COPY FROM STDIN).
@@ -63,7 +75,7 @@ export declare class IsolatedStoresApi {
63
75
  }): Promise<IsolatedStoreSqlCountResponseContract>;
64
76
  /**
65
77
  * Create isolated store
66
- * Registers a low-level store and binds it to the organization scope plus a isolated source scope such as app or app_feature.
78
+ * Registers a low-level store and binds it to the organization scope plus an isolated source scope such as app.
67
79
  */
68
80
  createIsolatedStore(params: {
69
81
  path: {
@@ -41,6 +41,21 @@ class IsolatedStoresApi {
41
41
  expectedContentType: "application/json",
42
42
  });
43
43
  }
44
+ /**
45
+ * Attach isolated store source scope
46
+ * Non-destructively grants an additional app source binding to an existing isolated store without changing stages or data. Useful when a store was originally created under an older app id but runtime app tokens need access.
47
+ */
48
+ async attachIsolatedStoreSourceScope(params) {
49
+ return this.client.request({
50
+ method: "POST",
51
+ path: "/:orgId/isolated-stores/:storeId/source-scopes",
52
+ pathParams: params.path,
53
+ headers: params.headers,
54
+ body: params.body,
55
+ opId: "attachIsolatedStoreSourceScope",
56
+ expectedContentType: "application/json",
57
+ });
58
+ }
44
59
  /**
45
60
  * Batch insert rows
46
61
  * Inserts multiple rows into a postgres table with a shared column set. Row cap per request is floor(65535 / columnCount) (Postgres bind-parameter limit). For very large loads use importIsolatedStoreSqlRows (COPY FROM STDIN).
@@ -73,7 +88,7 @@ class IsolatedStoresApi {
73
88
  }
74
89
  /**
75
90
  * Create isolated store
76
- * Registers a low-level store and binds it to the organization scope plus a isolated source scope such as app or app_feature.
91
+ * Registers a low-level store and binds it to the organization scope plus an isolated source scope such as app.
77
92
  */
78
93
  async createIsolatedStore(params) {
79
94
  return this.client.request({
@@ -375,6 +375,12 @@ export interface CreateIsolatedStoreRequestContract {
375
375
  export interface CreateIsolatedStoreResponseContract {
376
376
  store: IsolatedStoreContract;
377
377
  }
378
+ export interface AttachIsolatedStoreSourceScopeRequestContract {
379
+ source: IsolatedStoreSourceScopeContract;
380
+ }
381
+ export interface AttachIsolatedStoreSourceScopeResponseContract {
382
+ store: IsolatedStoreContract;
383
+ }
378
384
  export interface IsolatedStoreListResponseContract {
379
385
  stores: IsolatedStoreContract[];
380
386
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusebase/fusebase-gate-sdk",
3
- "version": "2.2.15-sdk.6",
3
+ "version": "2.2.15",
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",
@@ -1,14 +1,15 @@
1
- # Release Notes 2.2.15-sdk.6
1
+ # Release Notes 2.2.15-sdk.7
2
2
 
3
3
  - Current ref: `HEAD`
4
4
  - Previous tag: `v2.2.15-sdk.5`
5
- - Generated at: 2026-05-21T09:33:50.726Z
5
+ - Generated at: 2026-05-22T11:41:28.271Z
6
6
 
7
7
  ## Included Drafts
8
8
 
9
9
  - `docs/release-notes/2026-05-06-app-magic-links.md` - 2026-05-06-app-magic-links
10
10
  - `docs/release-notes/2026-05-20-app-magic-links-product-app-naming.md` - 2026-05-20-app-magic-links-product-app-naming
11
11
  - `docs/release-notes/2026-05-21-fusebase-auth-app-flows.md` - 2026-05-21-fusebase-auth-app-flows
12
+ - `docs/release-notes/2026-05-22-magic-link-access-principals-skills.md` - 2026-05-22 — Magic-link accessPrincipals and session-exchange skill guidance
12
13
 
13
14
  ## Summary
14
15
 
@@ -20,6 +21,10 @@ Surface AI App **Magic Link** flows through Gate. Three new ops let app owners a
20
21
 
21
22
  Update the `appMagicLinks` MCP prompt (and the regenerated `app-magic-links.md` skill reference) so it accounts for the `app → product` / `feature → app` rename. The magic-link **wire contract still uses the pre-rename field names** (`appId`, `appFeatureId`, `featureToken`), which no longer match the CLI (`fusebase.json`, `fusebase app list`). The stale skill caused agents to pass an App id where Gate expects a Product id, failing with `App not found`. No API, SDK, or permission changes — skill/prompt content only.
22
23
 
24
+ ### 2026-05-22 — Magic-link accessPrincipals and session-exchange skill guidance
25
+
26
+ Expand MCP prompt / skill guidance so agents and app builders do not confuse **org membership** with **App `accessPrincipals`** (silent `requestAppMagicLink` no-ops) and document the **post-activation** pattern: exchange `featureToken` + `sessionToken` on the app backend with `EverHelper-Session-ID` before relying on platform cookies.
27
+
23
28
 
24
29
  ## API / SDK Changes
25
30
 
@@ -80,6 +85,13 @@ Update the `appMagicLinks` MCP prompt (and the regenerated `app-magic-links.md`
80
85
  - `npm run mcp:skills:generate` — only `app-magic-links.md` rewritten.
81
86
  - `npm run mcp:skills:validate` — passes (1 skill).
82
87
 
88
+ ### 2026-05-22 — Magic-link accessPrincipals and session-exchange skill guidance
89
+
90
+ - `npm test -- --runInBand tests/unit/mcp-prompts.test.ts`
91
+ - `npm run mcp:skills:generate`
92
+ - `npm run mcp:skills:validate`
93
+ - `npm run mcp:skills:copy-to-apps-cli:local` (optional; propagates to `apps-cli/project-template`)
94
+
83
95
 
84
96
  ## Follow-ups
85
97
 
@@ -91,3 +103,20 @@ Update the `appMagicLinks` MCP prompt (and the regenerated `app-magic-links.md`
91
103
  ### 2026-05-20-app-magic-links-product-app-naming
92
104
 
93
105
  - Optional: align the magic-link wire field names (`appId` → `productId`, `appFeatureId` → `appId`) and the `nimbus-ai` `app_magic_links` columns with the new terminology. That is a contract/SDK change deferred as a separate product decision (see story-spec `NIM-40935/README.md` Open Questions); this change only makes the skill describe the current contract correctly.
106
+
107
+
108
+ ## Changes
109
+
110
+ ### 2026-05-22 — Magic-link accessPrincipals and session-exchange skill guidance
111
+
112
+ - `src/mcp/prompts/fusebase-auth.ts` — `1.0.0` → `1.1.0`: `accessPrincipals` vs org membership, Memberspace `--access` checklist, magic-link → app session exchange.
113
+ - `src/mcp/prompts/app-magic-links.ts` — `1.1.0` → `1.2.0`: self-service diagnostics, principals table, activation/session exchange section; clarify `sessionToken` vs `featureToken`.
114
+ - `src/mcp/prompts/users.ts` — `1.0.0` → `1.1.0`: `addOrgUser` does not grant app principals / magic-link dispatch.
115
+ - Regenerated `generated/claude_skills/fusebase-gate/references/{fusebase-auth,app-magic-links,users}.md`.
116
+
117
+
118
+ ## Consumer impact
119
+
120
+ ### 2026-05-22 — Magic-link accessPrincipals and session-exchange skill guidance
121
+
122
+ Documentation / agent guidance only — no API or permission changes.
@@ -0,0 +1,9 @@
1
+ # Release Notes 2.2.15
2
+
3
+ - Current ref: `HEAD`
4
+ - Previous tag: `v2.2.15`
5
+ - Generated at: 2026-05-26T09:07:29.777Z
6
+
7
+ ## Included Drafts
8
+
9
+ - None
@@ -1,93 +1,9 @@
1
- # Release Notes 2.2.15-sdk.6
1
+ # Release Notes 2.2.15
2
2
 
3
3
  - Current ref: `HEAD`
4
- - Previous tag: `v2.2.15-sdk.5`
5
- - Generated at: 2026-05-21T09:33:50.726Z
4
+ - Previous tag: `v2.2.15`
5
+ - Generated at: 2026-05-26T09:07:29.777Z
6
6
 
7
7
  ## Included Drafts
8
8
 
9
- - `docs/release-notes/2026-05-06-app-magic-links.md` - 2026-05-06-app-magic-links
10
- - `docs/release-notes/2026-05-20-app-magic-links-product-app-naming.md` - 2026-05-20-app-magic-links-product-app-naming
11
- - `docs/release-notes/2026-05-21-fusebase-auth-app-flows.md` - 2026-05-21-fusebase-auth-app-flows
12
-
13
- ## Summary
14
-
15
- ### 2026-05-06-app-magic-links
16
-
17
- Surface AI App **Magic Link** flows through Gate. Three new ops let app owners and runtime apps issue, request, and activate magic links against `nimbus-ai`'s storage layer. Ships with a new `appMagicLinks` MCP prompt group and the regenerated `app-magic-links.md` skill reference under `generated/claude_skills/fusebase-gate/references/`.
18
-
19
- ### 2026-05-20-app-magic-links-product-app-naming
20
-
21
- Update the `appMagicLinks` MCP prompt (and the regenerated `app-magic-links.md` skill reference) so it accounts for the `app → product` / `feature → app` rename. The magic-link **wire contract still uses the pre-rename field names** (`appId`, `appFeatureId`, `featureToken`), which no longer match the CLI (`fusebase.json`, `fusebase app list`). The stale skill caused agents to pass an App id where Gate expects a Product id, failing with `App not found`. No API, SDK, or permission changes — skill/prompt content only.
22
-
23
-
24
- ## API / SDK Changes
25
-
26
- ### 2026-05-06-app-magic-links
27
-
28
- - New ops in `src/api/contracts/ops/app-magic-links/app-magic-links.ts`:
29
- - `createAppMagicLink` — `POST /:orgId/apps/:appId/magic-links`. Owner/admin invite flow. Requires the new permission `app_magic_link.write` and org access.
30
- - `requestAppMagicLink` — `POST /apps/by-host/:host/magic-links/request`. Visitor self-service flow (no auth). Always returns `{ ok: true }` so it cannot be used to enumerate emails or access state. Apply per-IP rate limiting upstream.
31
- - `activateAppMagicLink` — `POST /apps/magic-links/:globalId/activate`. Visitor activation (no auth). Returns `{ id, sessionToken, featureToken, dashboardToken, redirectPath, expiresAt, appFeatureId }`. Surfaces `403` with `reason=expired|revoked` and `404` for unknown/deleted links.
32
- - New permission `app_magic_link.write` registered in `GatePermission` and granted to owner/manager/member/guest roles via the existing `GATE_ALL_PERMISSIONS` set.
33
- - New controller `AppMagicLinksController` (`src/controllers/app-magic-links/app-magic-links.ts`) and nimbus-ai client wrapper `src/clients/app-magic-link-client.ts`. The wrapper forwards the caller's userId via the standard `Authorization: Internal <userId>:gate` + `X-Secret` header pair on the create endpoint, and only `X-Secret` on the visitor endpoints.
34
- - Bumped `@internal/nimbus-ai` peer to `^1.58.0` to pick up the new `apiCreateAppMagicLink`, `apiRequestAppMagicLink`, and `apiActivateAppMagicLink` methods. The 1.58.0 client is published by the nimbus-ai NIM-40935 MR (`internal/nimbus-ai!65`); CI on this MR will be red until that MR lands and the registry has 1.58.0.
35
-
36
- ### 2026-05-20-app-magic-links-product-app-naming
37
-
38
- - None. The HTTP contracts, SDK, OpenAPI spec, and permissions are unchanged.
39
-
40
-
41
- ## Consumer Impact
42
-
43
- ### 2026-05-06-app-magic-links
44
-
45
- - New SDK domain `AppMagicLinksApi` with three methods (`createAppMagicLink`, `requestAppMagicLink`, `activateAppMagicLink`) materialized in `generated/sdk-client/src/apis/AppMagicLinksApi.ts`.
46
- - New SDK type module `generated/sdk-client/src/types/app-magic-link/`.
47
- - Apps that want to ship a one-click client onboarding flow can now invite-by-email (with optional `addToAccessPrincipals=true` to provision a brand-new user) and surface a `/link?id=…&redirect=…` route in their SPA scaffold (see follow-up subtask NIM-41013 for the apps-cli template).
48
- - The `request` endpoint never mutates `accessPrincipals` and never provisions users, by design — visitors can self-service only when they already have access.
49
- - New MCP prompt group `appMagicLinks` (registered in `src/mcp/prompts/index.ts`) covers when to use each flow, deep-link `redirectPath` rules, and expired/revoked link handling. The op contracts declare `promptGroups: ["authz", "sdk", "appMagicLinks"]` (authed) and `["sdk", "appMagicLinks"]` (visitor), so prompt-aware MCP clients receive the guidance automatically.
50
- - New skill reference file `generated/claude_skills/fusebase-gate/references/app-magic-links.md` (marker `mcp-app-magic-links-loaded`). `npm run mcp:skills:copy-to-apps-cli:local` propagates it into `apps-cli/project-template/.claude/skills/fusebase-gate/references/` for fresh `fusebase init` output.
51
-
52
- ### 2026-05-20-app-magic-links-product-app-naming
53
-
54
- - `src/mcp/prompts/app-magic-links.ts` — bumped `version` `1.0.0` → `1.1.0`. New "Terminology: `product` / `app` vs the Gate wire contract" section maps the renamed concepts onto the unchanged wire fields:
55
- - `createAppMagicLink`'s `appId` **path segment** is the **Product id** (`productId` in `fusebase.json`), not an App id.
56
- - `appFeatureId` in the activation response and the scope of `featureToken` is an **App** id (`apps[].id` / `fusebase app list`).
57
- - The wire field names stay at their pre-rename spelling for backward compatibility; only the human-facing concepts were renamed.
58
- - The Invite-flow, Identity/Scoping, Activation, and Working-Rules sections now use `Product` / `App` consistently ("every App of the Product", "App-scoped by host", etc.) and call out the `App not found` failure mode explicitly.
59
- - The Activation section now folds in the SPA `fetch`-vs-SDK note and the `fbsdashboardtoken` cookie detail, so the next `mcp:skills:copy-to-apps-cli` no longer reverts the apps-cli-side hand edits — the generated skill is the single source of truth again.
60
- - Regenerated `generated/claude_skills/fusebase-gate/references/app-magic-links.md` (frontmatter `version: 1.1.0`). `apps-cli` receives the same file under `project-template/.claude/skills/fusebase-gate/references/`.
61
-
62
-
63
- ## Verification
64
-
65
- ### 2026-05-06-app-magic-links
66
-
67
- - `npm run lint`
68
- - `npm test` (190 tests pass; new tests in `tests/unit/app-magic-links-contracts.test.ts` and `tests/unit/app-magic-links-controller.test.ts`)
69
- - `npm run build`
70
- - `FEATURE_FLAGS=isolated_sql_stores,isolated_nosql_stores npm run build:sdk` — SDK regenerated, `dist/apis/AppMagicLinksApi.{js,d.ts}` and `dist/types/app-magic-link/` produced; OpenAPI spec updated.
71
- - `npm run mcp:skills:generate` — `app-magic-links.md` written under `generated/claude_skills/fusebase-gate/references/`; `SKILL.md` TOC updated.
72
- - `npm run mcp:skills:validate` — passes (1 skill).
73
- - `npm run mcp:skills:copy-to-apps-cli:local` — generated skill copied into the local apps-cli checkout (commit owned by NIM-41013).
74
-
75
- ### 2026-05-20-app-magic-links-product-app-naming
76
-
77
- - `npm run build` — clean.
78
- - `npm run lint` — 0 errors (5 pre-existing `dist/` warnings).
79
- - `npm test` — 216 pass / 1 skipped, including the new `mcp-prompts.test.ts` case `maps the product/app rename onto the magic-link wire contract`.
80
- - `npm run mcp:skills:generate` — only `app-magic-links.md` rewritten.
81
- - `npm run mcp:skills:validate` — passes (1 skill).
82
-
83
-
84
- ## Follow-ups
85
-
86
- ### 2026-05-06-app-magic-links
87
-
88
- - **CI dependency:** the dependency bump to `@internal/nimbus-ai@^1.58.0` requires `internal/nimbus-ai!65` (NIM-40935) to merge and publish 1.58.0 to the GitLab npm registry. After it merges, this branch should be rebased and `npm install` re-run to refresh the lock file with the upstream-published integrity hash.
89
- - **NIM-41013:** receive the generated skill in `apps-cli` and ship the `/link` route example in `feature-templates/spa/`. The skill file is already in the local apps-cli working tree from `mcp:skills:copy-to-apps-cli:local`; NIM-41013 owns the apps-cli commit.
90
-
91
- ### 2026-05-20-app-magic-links-product-app-naming
92
-
93
- - Optional: align the magic-link wire field names (`appId` → `productId`, `appFeatureId` → `appId`) and the `nimbus-ai` `app_magic_links` columns with the new terminology. That is a contract/SDK change deferred as a separate product decision (see story-spec `NIM-40935/README.md` Open Questions); this change only makes the skill describe the current contract correctly.
9
+ - None