Skip to content

OUT-3977 | Platform layer: extend AssemblyClient for installs notificationConfig + notification appId - #218

Merged
arpandhakal merged 3 commits into
feature/studio-apps-actionfrom
arpandhakal/out-3977-platform-layer-extend-assemblyclient-for-installs
Jul 21, 2026
Merged

OUT-3977 | Platform layer: extend AssemblyClient for installs notificationConfig + notification appId#218
arpandhakal merged 3 commits into
feature/studio-apps-actionfrom
arpandhakal/out-3977-platform-layer-extend-assemblyclient-for-installs

Conversation

@arpandhakal

Copy link
Copy Markdown
Collaborator

Changes

Platform-layer (src/lib/assembly) support so Client Home can discover Studio apps' registered action labels and bucket notifications by app. Client Home stays a pure consumer — no registration surface, no new stored state in this ticket.

  • AppInstallsDataSchema — added icon, disabled, isDraft, isInternalApp (all nullish; the SDK's generated types don't declare them). No notificationConfig — it is not inlined on GET /v1/installs.
  • New schemas for GET /v1/installs/{id}/notification-settings: ActionLabelSchema (verb, singularNoun, pluralNoun) and InstallNotificationSettingsSchema, plus an isActionLabelRegistered helper that treats a label as registered only when all three parts are present and non-empty.
  • NotificationsResponseSchema — added appId (nullish), the bucketing key for custom-app notifications. Also relaxed event to nullish (matches the SDK's event?: string and avoids a parse throw if a custom-app notification omits it).
  • AssemblyClient.getInstalls() — wraps the SDK's listAppInstalls() (GET /v1/installs returns a bare array with no pagination cursor, so a single fetch is complete).
  • AssemblyClient.getInstallNotificationSettings(installId) — the SDK exposes no method for the notification-settings sub-resource, so this goes through a new private _manualFetch helper (base URL from the SDK's OpenAPI.BASE, X-API-KEY built from workspaceId + api key). Both new methods are wrapped with wrapWithRetry.
  • Minor: _getAppId now reuses getInstalls() instead of duplicating the parse.

Deliberately out of scope for this PR: nextToken pagination on the notifications fetch. The notifications fetch stays on the existing single SDK call — the per-app count consumer (OUT-3980) will address pagination there if needed.

Testing Criteria

  • pnpm typecheck passes
  • pnpm lint passes
  • Existing unit tests pass (23/23)
  • Staging runtime check (pending): verify against staging that icon/disabled/isDraft/isInternalApp come through on installs, that appId appears on notifications, and — highest risk — that actionLabel sits at the top level of the notification-settings response rather than nested under a wrapper. If nested, it's a one-line schema adjustment. (Loom to follow after the staging check.)

Notes

  • Unblocks OUT-3979 (discovery endpoint) and OUT-3980 (per-app counts), which consume getInstalls() / getInstallNotificationSettings() and the appId field respectively.
  • The SDK's generated TS types are behind the platform API, so several new fields are typed via Zod as nullish and verified at runtime rather than from SDK types.

Impact & Surface Area of Change

  • getNotifications behavior is unchanged (same SDK call, same shape) — existing notification counts are unaffected. Only additive schema fields (appId, and event relaxed from required to nullish).
  • _getAppId was refactored to delegate to getInstalls(); behavior is identical (same filter on appId).
  • New code paths (getInstalls, getInstallNotificationSettings, _manualFetch) have no callers yet in this PR, so no runtime surface changes for existing features.

🤖 Generated with Claude Code

…ppId

Extend the platform layer so Client Home can discover Studio apps' action
labels and bucket notifications by app.

- AppInstallsDataSchema: add icon, disabled, isDraft, isInternalApp
- Add ActionLabelSchema + InstallNotificationSettingsSchema for
  GET /v1/installs/{id}/notification-settings, plus isActionLabelRegistered
- NotificationsResponseSchema: add appId (nullish); relax event to nullish
- AssemblyClient.getInstalls() and getInstallNotificationSettings(installId),
  the latter via a _manualFetch helper since the SDK exposes no method for
  the notification-settings sub-resource

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@linear-code

linear-code Bot commented Jul 21, 2026

Copy link
Copy Markdown

OUT-3977

@vercel

vercel Bot commented Jul 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
client-home-v3 Ready Ready Preview, Comment Jul 21, 2026 9:18am

Request Review

@greptile-apps

greptile-apps Bot commented Jul 21, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds platform-layer support for Assembly installs and notification metadata. The main changes are:

  • New install fields for icon and app state metadata.
  • New notification-settings schemas and a manual fetch path for install notification settings.
  • Notification parsing now includes appId and allows missing events.
  • App install lookup now reuses the shared installs helper.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.
  • The transient HTTP error handling now keeps the status available for retry decisions.
  • The schema updates are additive or relax existing parsing behavior.

Important Files Changed

Filename Overview
src/lib/assembly/assembly-client.ts Adds install helpers and manual notification-settings fetching, with status-aware error handling for failed responses.
src/lib/assembly/types.ts Adds install metadata, notification-settings schemas, and notification appId parsing.

Reviews (2): Last reviewed commit: "fix(OUT-3977): preserve HTTP status on m..." | Re-trigger Greptile

Comment thread src/lib/assembly/assembly-client.ts Outdated
Comment thread src/lib/assembly/assembly-client.ts Outdated
…orks

Check response.ok before parsing the body in _manualFetch. A transient
429/500 with a non-JSON body previously threw a statusless SyntaxError,
which withRetry could not recognize as retryable. Now read the error body
as text and throw APIError with the real status.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@arpandhakal

Copy link
Copy Markdown
Collaborator Author

please re review @greptile

@arpandhakal
arpandhakal changed the base branch from main to feature/studio-apps-action July 21, 2026 08:56
Comment thread src/lib/assembly/types.ts Outdated
…var for API URL

- Replace the manual isActionLabelRegistered checks with a strict
  RegisteredActionLabelSchema (trim + non-empty), per PR review
- Use env.ASSEMBLY_API_URL (default prod) as the base URL in _manualFetch
  instead of the SDK's mutable OpenAPI.BASE global; drop the OpenAPI import

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@priosshrsth priosshrsth left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm.

@arpandhakal
arpandhakal merged commit 39feb46 into feature/studio-apps-action Jul 21, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants