Skip to content

feat(callbacks): add Community Apps alpha contracts#52

Open
elibosley wants to merge 5 commits into
alphafrom
codex/community-apps-alpha-contracts
Open

feat(callbacks): add Community Apps alpha contracts#52
elibosley wants to merge 5 commits into
alphafrom
codex/community-apps-alpha-contracts

Conversation

@elibosley
Copy link
Copy Markdown
Member

@elibosley elibosley commented Jun 3, 2026

Summary

  • add Community Apps launch contract support for opt-in installed app lookup, install bridge actions, and structured theme payloads
  • add typed requestInstall host bridge method and install response shape for Core iframe integration
  • add default export targets for shared-callbacks subpaths so @unraid/shared-callbacks/client resolves in stricter dev tooling
  • rebuild published dist declarations/bundles

Alpha release path

  • This PR now targets alpha, not main.
  • After merge, the alpha publish workflow from ci(callbacks): add alpha publish workflow #53 should publish this package under the npm alpha dist-tag.
  • CA/Core can test with @unraid/shared-callbacks@alpha without affecting the stable latest package.

Supersedes

Verification

  • pnpm run build
  • pnpm test -- --run src/__tests__/server.test.ts
  • verified @unraid/shared-callbacks/client resolves from the CA worker linked package
  • verified CA worker vue-tsc passes against this linked branch

Summary by CodeRabbit

  • New Features

    • Community Apps support for managing installations and app status
    • Secure iframe-based communication bridge with community apps
    • Installed app hashing and validation
  • Documentation

    • Added Community Apps API reference to README
  • Chores

    • Updated package exports for enhanced compatibility
    • Added new production dependency
  • Tests

    • Added Community Apps functionality test coverage

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bcc943ce-2ec2-49e2-ac7b-fb1988bbc244

📥 Commits

Reviewing files that changed from the base of the PR and between 8dbae71 and 2f90748.

⛔ Files ignored due to path filters (9)
  • dist/client.d.ts is excluded by !**/dist/**
  • dist/client.js is excluded by !**/dist/**
  • dist/community-apps-client.d.ts is excluded by !**/dist/**
  • dist/community-apps.d.ts is excluded by !**/dist/**
  • dist/index.js is excluded by !**/dist/**
  • dist/server.d.ts is excluded by !**/dist/**
  • dist/server.js is excluded by !**/dist/**
  • dist/types.d.ts is excluded by !**/dist/**
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (9)
  • README.md
  • package.json
  • src/__tests__/server.test.ts
  • src/client.ts
  • src/community-apps-client.ts
  • src/community-apps.ts
  • src/post-me.d.ts
  • src/server.ts
  • src/types.ts
✅ Files skipped from review due to trivial changes (1)
  • src/post-me.d.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/community-apps.ts
  • src/types.ts
  • src/server.ts
  • src/tests/server.test.ts
  • src/community-apps-client.ts
  • src/client.ts

📝 Walkthrough

Walkthrough

This PR adds Community Apps launch callback infrastructure including a complete type system for installed-app management, SHA256-based app hashing, client-side iframe bridge communication, and updated public APIs for both client and server modules with supporting tests and documentation.

Changes

Community Apps Feature

Layer / File(s) Summary
Community Apps Type System
src/types.ts
Defines complete type hierarchy for Community Apps including CommunityAppsLaunch interface with server data, optional installed-apps, install actions, and theming; adds status enums, algorithms, modes, and request/response shapes; extends UpcActions union.
Installed App Hashing Utilities
src/community-apps.ts
Implements sha256-128 hashing for app identifiers with fixed 22-character URL-safe format; exports hash creation, validation, algorithm constant, and length constant.
post-me Module Declarations
src/post-me.d.ts
Declares TypeScript types for external post-me library covering WindowMessenger constructor and ParentHandshake function with handshake retry configuration.
Client-Side iframe Bridge
src/community-apps-client.ts
Implements typed host-side bridge for iframe communication via post-me ParentHandshake; exposes methods for installed-app status queries and optional install requests with configurable retry behavior.
Client Public API Exports
src/client.ts
Re-exports Community Apps types, hash utilities, status enum, and bridge factory from internal modules; maintains backward compatibility.
Server Public API Exports
src/server.ts
Re-exports Community Apps types, hash utilities, and status enum from internal modules; maintains backward compatibility.
Package Configuration
package.json
Updates exports map with import/default entry points for root and client/server subpaths; adds post-me runtime dependency.
Tests and Documentation
src/__tests__/server.test.ts, README.md
Adds round-trip test for CommunityAppsLaunch encryption/decryption and validation of hash format/salt-dependency; documents Community Apps API types and installedApps opt-in constraints with algorithm/salt requirements.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A new village for apps to call home,
With hashes that guard, and bridges to roam,
Through iframes they journey with messages true,
TypeScript ensures every path runs right through,
Community thrives when connections are tight! 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title follows the conventional commits format with the 'feat' type and includes a descriptive scope and subject that accurately summarize the main changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/community-apps-alpha-contracts
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch codex/community-apps-alpha-contracts

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 3, 2026

Codecov Report

❌ Patch coverage is 59.09091% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.36%. Comparing base (8c6afd7) to head (2f90748).

Files with missing lines Patch % Lines
src/community-apps-client.ts 14.28% 6 Missing ⚠️
src/community-apps.ts 75.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            alpha      #52      +/-   ##
==========================================
- Coverage   99.08%   92.36%   -6.72%     
==========================================
  Files           3        6       +3     
  Lines         109      131      +22     
  Branches       30       36       +6     
==========================================
+ Hits          108      121      +13     
- Misses          1       10       +9     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/client.ts (1)

24-52: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Re-export the new theme/base contract types from the client entrypoint.

The client subpath still omits CommunityAppsInstalledAppsBase, CommunityAppsThemeColorMode, CommunityAppsThemeVariables, and CommunityAppsThemePayload. That leaves the new Community Apps surface only partially consumable from @unraid/shared-callbacks/client, which defeats the alpha contract for downstream consumers.

Proposed fix
 import type {
   CallbackConfig,
   QueryPayloads,
   SendPayloads,
@@
   CommunityAppsInstalledAppsAlgorithm,
   CommunityAppsInstalledAppsMode,
   CommunityAppsInstalledAppHash,
   CommunityAppsInstalledAppStatusMap,
+  CommunityAppsInstalledAppsBase,
   CommunityAppsInstalledAppsBatch,
   CommunityAppsInstalledAppsLookup,
   CommunityAppsInstalledApps,
+  CommunityAppsThemeColorMode,
+  CommunityAppsThemeVariables,
+  CommunityAppsThemePayload,
   CommunityAppsInstalledAppStatusRequest,
   CommunityAppsInstalledAppStatusResponse,
   CommunityAppsInstallActionType,
@@
 export type {
   CallbackConfig,
   QueryPayloads,
   SendPayloads,
@@
   CommunityAppsInstalledAppsAlgorithm,
   CommunityAppsInstalledAppsMode,
   CommunityAppsInstalledAppHash,
   CommunityAppsInstalledAppStatusMap,
+  CommunityAppsInstalledAppsBase,
   CommunityAppsInstalledAppsBatch,
   CommunityAppsInstalledAppsLookup,
   CommunityAppsInstalledApps,
+  CommunityAppsThemeColorMode,
+  CommunityAppsThemeVariables,
+  CommunityAppsThemePayload,
   CommunityAppsInstalledAppStatusRequest,
   CommunityAppsInstalledAppStatusResponse,
   CommunityAppsInstallActionType,

Also applies to: 215-272

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/client.ts` around lines 24 - 52, The client entrypoint export list is
missing several new Community Apps contract types — add
CommunityAppsInstalledAppsBase, CommunityAppsThemeColorMode,
CommunityAppsThemeVariables, and CommunityAppsThemePayload to the exported
symbols alongside the existing CommunityApps and CommunityAppsLaunch entries;
update both export blocks that export CommunityApps-related types (the earlier
block that includes CommunityApps, CommunityAppsLaunch, etc. and the later
similar export block) so the full Community Apps surface is re-exported from the
client entrypoint (ensure you reference the exact type names:
CommunityAppsInstalledAppsBase, CommunityAppsThemeColorMode,
CommunityAppsThemeVariables, CommunityAppsThemePayload).
src/server.ts (1)

23-51: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Mirror the missing Community Apps theme/base exports on the server entrypoint.

@unraid/shared-callbacks/server has the same gap as the client entry: CommunityAppsInstalledAppsBase, CommunityAppsThemeColorMode, CommunityAppsThemeVariables, and CommunityAppsThemePayload are defined in src/types.ts but never surfaced here. That leaves the shared server contract incomplete for downstream users.

Proposed fix
 import type {
   CallbackConfig,
   QueryPayloads,
   SendPayloads,
@@
   CommunityAppsInstalledAppsAlgorithm,
   CommunityAppsInstalledAppsMode,
   CommunityAppsInstalledAppHash,
   CommunityAppsInstalledAppStatusMap,
+  CommunityAppsInstalledAppsBase,
   CommunityAppsInstalledAppsBatch,
   CommunityAppsInstalledAppsLookup,
   CommunityAppsInstalledApps,
+  CommunityAppsThemeColorMode,
+  CommunityAppsThemeVariables,
+  CommunityAppsThemePayload,
   CommunityAppsInstalledAppStatusRequest,
   CommunityAppsInstalledAppStatusResponse,
   CommunityAppsInstallActionType,
@@
 export type {
   CallbackConfig,
   QueryPayloads,
   SendPayloads,
@@
   CommunityAppsInstalledAppsAlgorithm,
   CommunityAppsInstalledAppsMode,
   CommunityAppsInstalledAppHash,
   CommunityAppsInstalledAppStatusMap,
+  CommunityAppsInstalledAppsBase,
   CommunityAppsInstalledAppsBatch,
   CommunityAppsInstalledAppsLookup,
   CommunityAppsInstalledApps,
+  CommunityAppsThemeColorMode,
+  CommunityAppsThemeVariables,
+  CommunityAppsThemePayload,
   CommunityAppsInstalledAppStatusRequest,
   CommunityAppsInstalledAppStatusResponse,
   CommunityAppsInstallActionType,

Also applies to: 111-166

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/server.ts` around lines 23 - 51, Export the missing Community Apps type
symbols from the server entrypoint so the shared server contract matches the
client: add CommunityAppsInstalledAppsBase, CommunityAppsThemeColorMode,
CommunityAppsThemeVariables, and CommunityAppsThemePayload to the export lists
in src/server.ts (the same places where CommunityAppsInstalledApps,
CommunityAppsInstallRequest, CommunityAppsLaunch, etc. are exported) and ensure
the duplicate export blocks (the later block covering lines ~111-166) also
include these four types so both export groups surface them.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/post-me.d.ts`:
- Around line 1-16: Update the post-me declarations to match post-me@0.4.5:
extend the WindowMessenger type to include the instance methods
addMessageListener(listener: MessageListener): ListenerRemover and
postMessage(message: any, transfer?: Transferable[]): void in addition to the
constructor, and change ParentHandshake to the generic signature used
upstream—accept messenger: Messenger, localMethods?: M0 with M0 extends
MethodsType, and return Promise<Connection> (rather than constraining messenger
to WindowMessenger, using Record<string, ...>, or returning { close: () => void
}); use the exact type names Messenger, MethodsType, M0, and Connection from the
upstream definitions so callers get correct typings.

---

Outside diff comments:
In `@src/client.ts`:
- Around line 24-52: The client entrypoint export list is missing several new
Community Apps contract types — add CommunityAppsInstalledAppsBase,
CommunityAppsThemeColorMode, CommunityAppsThemeVariables, and
CommunityAppsThemePayload to the exported symbols alongside the existing
CommunityApps and CommunityAppsLaunch entries; update both export blocks that
export CommunityApps-related types (the earlier block that includes
CommunityApps, CommunityAppsLaunch, etc. and the later similar export block) so
the full Community Apps surface is re-exported from the client entrypoint
(ensure you reference the exact type names: CommunityAppsInstalledAppsBase,
CommunityAppsThemeColorMode, CommunityAppsThemeVariables,
CommunityAppsThemePayload).

In `@src/server.ts`:
- Around line 23-51: Export the missing Community Apps type symbols from the
server entrypoint so the shared server contract matches the client: add
CommunityAppsInstalledAppsBase, CommunityAppsThemeColorMode,
CommunityAppsThemeVariables, and CommunityAppsThemePayload to the export lists
in src/server.ts (the same places where CommunityAppsInstalledApps,
CommunityAppsInstallRequest, CommunityAppsLaunch, etc. are exported) and ensure
the duplicate export blocks (the later block covering lines ~111-166) also
include these four types so both export groups surface them.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1be91ddd-900d-4c5b-ba92-137d7eb8941f

📥 Commits

Reviewing files that changed from the base of the PR and between 6181363 and 8dbae71.

⛔ Files ignored due to path filters (9)
  • dist/client.d.ts is excluded by !**/dist/**
  • dist/client.js is excluded by !**/dist/**
  • dist/community-apps-client.d.ts is excluded by !**/dist/**
  • dist/community-apps.d.ts is excluded by !**/dist/**
  • dist/index.js is excluded by !**/dist/**
  • dist/server.d.ts is excluded by !**/dist/**
  • dist/server.js is excluded by !**/dist/**
  • dist/types.d.ts is excluded by !**/dist/**
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (10)
  • README.md
  • package.json
  • src/__tests__/server.test.ts
  • src/client.ts
  • src/community-apps-client.ts
  • src/community-apps.ts
  • src/post-me.d.ts
  • src/server.ts
  • src/types.ts
  • tsconfig.json

Comment thread src/post-me.d.ts
Comment on lines +1 to +16
declare module "post-me" {
export class WindowMessenger {
constructor(options: {
localWindow?: Window;
remoteWindow: Window;
remoteOrigin: string;
});
}

export function ParentHandshake(
messenger: WindowMessenger,
localMethods?: Record<string, (...args: any[]) => any>,
maxAttempts?: number,
attemptsInterval?: number
): Promise<{ close: () => void }>;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

What is the API signature for WindowMessenger and ParentHandshake in post-me version 0.4.5?

💡 Result:

WindowMessenger (post-me v0.4.5) Constructor signature: export declare class WindowMessenger implements Messenger constructor({ localWindow, remoteWindow, remoteOrigin, }): void Supported instance methods (from the WindowMessenger type docs): - addMessageListener(listener: MessageListener): ListenerRemover - postMessage(message: any, transfer?: Transferable[]): void [1] ParentHandshake (post-me v0.4.5) Function signature: export declare function ParentHandshake( messenger: Messenger, localMethods?: M0, maxAttempts?: number, attemptsInterval?: number): Promise; [2]

Citations:


Align src/post-me.d.ts with post-me@0.4.5 types.

  • WindowMessenger is missing documented instance methods: addMessageListener(listener: MessageListener): ListenerRemover and postMessage(message: any, transfer?: Transferable[]): void (only the constructor is declared).
  • ParentHandshake signature doesn’t match post-me@0.4.5: it should return Promise<Connection> and use messenger: Messenger plus localMethods?: M0 with M0 extends MethodsType; the current declaration narrows messenger to WindowMessenger, types localMethods as Record<string, (...args: any[]) => any>, and returns Promise<{ close: () => void }> instead.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/post-me.d.ts` around lines 1 - 16, Update the post-me declarations to
match post-me@0.4.5: extend the WindowMessenger type to include the instance
methods addMessageListener(listener: MessageListener): ListenerRemover and
postMessage(message: any, transfer?: Transferable[]): void in addition to the
constructor, and change ParentHandshake to the generic signature used
upstream—accept messenger: Messenger, localMethods?: M0 with M0 extends
MethodsType, and return Promise<Connection> (rather than constraining messenger
to WindowMessenger, using Record<string, ...>, or returning { close: () => void
}); use the exact type names Messenger, MethodsType, M0, and Connection from the
upstream definitions so callers get correct typings.

elibosley added 5 commits June 3, 2026 16:16
- Add a typed communityApps action for Unraid OS to launch Community Apps inside an iframe.

- Before, callback payloads only modeled account, license, and OS update actions.

- That left CA iframe launches without a shared contract for server context, install targets, or theme/path preferences.

- Add CommunityAppsLaunch to the UPC action union with server data and optional install URL customization fields.

- Export the new action type through client and server entrypoints and cover server round-trip generation/parsing.

- Regenerate package declaration files so consumers can type against the new contract.
- Add an explicit installedApps payload block for Community Apps launches.

- Before, the launch action had no contract for installed-state exposure.

- That made it unclear how Core should represent optional installed app matching without weakening the privacy boundary.

- Model installed app fingerprints as an optional enabled:true block with algorithm, salt, and keys.

- Keep the field omitted unless a user opts into local installed-state badges.
- Replace the flat installed app fingerprint list with a compact status map.

- Before, callbacks could only say that a hash was present, so CA could not distinguish currently installed apps from previously installed apps.

- Variable-length hash strings also risked wasting URL space in hash-based iframe launches.

- Add numeric installed app status codes and fixed sha256-128 app fingerprints encoded as 22-character base64url keys.

- Export the status enum through client and server entrypoints so Core can build payloads without hardcoding status values.
- Add lookup mode for Community Apps installed app status payloads.

- Before, status context had to be carried as a launch-time app map when CA needed installed-state UI.

- That exposed more installed-app information than necessary and could grow callback URLs.

- Add fixed-length salted app hash helpers and a post-me parent bridge for visible-app status lookups.

- Keep batch maps available while making lookup mode the preferred privacy-preserving integration.
Purpose of the change

- Add the remaining Community Apps iframe contracts needed by CA/Core integration.

Previous behavior

- Shared callbacks only described installed-app status lookup for Community Apps.

- The package subpath exports only declared import/type conditions, which left some dev tooling unable to resolve @unraid/shared-callbacks/client.

Why that was a problem

- CA and Core need a typed postMessage install request path, richer theme payloads, and explicit install review responses before this can be consumed outside local links.

- Resolver failures blocked vue-tsc in consumers using the linked package.

What the new change accomplishes

- Adds typed Community Apps install bridge actions, requests, and responses.

- Allows structured light/dark/shared theme payloads while preserving simple color mode strings.

- Exports the new types from client and server entrypoints.

- Adds default package export targets for Node/tooling compatibility.

How it works

- Extends CommunityAppsLaunch with optional installAction and structured theme payloads.

- Adds requestInstall to the Community Apps host bridge method contract.

- Rebuilds dist declarations and bundles from the source types.
@elibosley elibosley force-pushed the codex/community-apps-alpha-contracts branch from 8dbae71 to 2f90748 Compare June 3, 2026 20:16
@elibosley elibosley changed the base branch from main to alpha June 3, 2026 20:17
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.

1 participant