Skip to content

Commit 3f146a7

Browse files
os-zhuangclaude
andcommitted
feat(cloud-connection): marketplace Setup nav is plugin-owned (ADR-0029 K2 handoff)
Browse Marketplace ships with MarketplaceProxyPlugin; Installed Apps ships with MarketplaceInstallLocalPlugin — the entry lives and dies with the capability (OS_CLOUD_URL=off → no marketplace entries at all, instead of a dead page). Removed from platform-objects' setup-nav contributions per its own 'entries move out into capability plugins' direction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent c2a3c38 commit 3f146a7

6 files changed

Lines changed: 88 additions & 2 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@objectstack/cloud-connection": minor
3+
"@objectstack/platform-objects": minor
4+
---
5+
6+
Marketplace Setup navigation is now plugin-owned (cloud ADR-0009): `MarketplaceProxyPlugin` carries the "Browse Marketplace" entry and `MarketplaceInstallLocalPlugin` carries "Installed Apps" — no plugin mounted (e.g. `OS_CLOUD_URL=off`), no entry, no dead page. The two entries are removed from `@objectstack/platform-objects`' setup-nav contributions (ADR-0029 K2 ownership handoff).

packages/cloud-connection/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,4 @@ export type { RuntimeConfigPluginConfig, RuntimeConfigPlanFeatures } from './run
4949
export { ConnectionCredentialStore, DEFAULT_CONNECTION_CREDENTIAL_PATH } from './connection-credential-store.js';
5050
export type { StoredConnectionCredential } from './connection-credential-store.js';
5151
export { CloudConnectionSettingsPage, CLOUD_CONNECTION_UI_BUNDLE } from './cloud-connection-ui.js';
52+
export { MARKETPLACE_BROWSE_UI_BUNDLE, MARKETPLACE_INSTALLED_UI_BUNDLE } from './marketplace-ui.js';

packages/cloud-connection/src/marketplace-install-local-plugin.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import { resolveCloudUrl } from './cloud-url.js';
4747
import { resolveMarketplacePublicBaseUrl } from './marketplace-public-url.js';
4848
import { LocalManifestSource, type InstalledManifestEntry } from './local-manifest-source.js';
4949
import { ConnectionCredentialStore } from './connection-credential-store.js';
50+
import { MARKETPLACE_INSTALLED_UI_BUNDLE } from './marketplace-ui.js';
5051

5152
const ROUTE_BASE = '/api/v1/marketplace/install-local';
5253

@@ -88,6 +89,13 @@ export class MarketplaceInstallLocalPlugin implements Plugin {
8889

8990
start = async (ctx: PluginContext): Promise<void> => {
9091
ctx.hook('kernel:ready', async () => {
92+
// Plugin-owned Setup nav (cloud ADR-0009): "Installed Apps"
93+
// ships WITH the local-install capability.
94+
try {
95+
const manifest = ctx.getService<{ register(m: any): void }>('manifest');
96+
manifest?.register?.(MARKETPLACE_INSTALLED_UI_BUNDLE);
97+
} catch { /* no manifest service */ }
98+
9199
// 1. Rehydrate previously installed packages so they survive restart.
92100
await this.rehydrate(ctx);
93101

packages/cloud-connection/src/marketplace-proxy-plugin.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import type { Plugin, PluginContext } from '@objectstack/core';
2929
import { resolveCloudUrl } from './cloud-url.js';
30+
import { MARKETPLACE_BROWSE_UI_BUNDLE } from './marketplace-ui.js';
3031
import {
3132
resolveMarketplacePublicBaseUrl,
3233
publicMarketplaceKeyForApiPath,
@@ -171,6 +172,15 @@ export class MarketplaceProxyPlugin implements Plugin {
171172

172173
start = async (ctx: PluginContext): Promise<void> => {
173174
ctx.hook('kernel:ready', async () => {
175+
// Plugin-owned Setup nav (cloud ADR-0009): the "Browse
176+
// Marketplace" entry ships WITH the browse capability — no
177+
// proxy mounted, no entry. Best-effort: headless kernels
178+
// simply have no Setup surface.
179+
try {
180+
const manifest = ctx.getService<{ register(m: any): void }>('manifest');
181+
manifest?.register?.(MARKETPLACE_BROWSE_UI_BUNDLE);
182+
} catch { /* no manifest service */ }
183+
174184
let httpServer: any;
175185
try {
176186
httpServer = ctx.getService('http-server');
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
/**
4+
* Marketplace — plugin-owned Setup navigation (cloud ADR-0009: cloud
5+
* functionality ships as plugins carrying their FULL UI surface).
6+
*
7+
* Ownership moved here from `@objectstack/platform-objects`'
8+
* setup-nav.contributions.ts (ADR-0029 K2's standing direction): the nav
9+
* entry now lives and dies with the capability —
10+
*
11+
* - no MarketplaceProxyPlugin mounted (`OS_CLOUD_URL=off`) → no
12+
* "Browse Marketplace" entry → no dead page.
13+
* - no MarketplaceInstallLocalPlugin → no "Installed Apps" entry.
14+
*
15+
* The URLs still point at the console's existing marketplace routes; the
16+
* pages themselves migrate to plugin-carried metadata in later ADR-0009
17+
* stages (Installed Apps first).
18+
*/
19+
20+
/** "Browse Marketplace" — owned by the browse capability (the proxy). */
21+
export const MARKETPLACE_BROWSE_UI_BUNDLE = {
22+
id: 'com.objectstack.cloud-connection.marketplace-browse-ui',
23+
namespace: 'sys',
24+
version: '0.1.0',
25+
type: 'plugin',
26+
scope: 'system',
27+
name: 'Marketplace Browse UI',
28+
description: 'Setup navigation for the public marketplace catalog (browse).',
29+
navigationContributions: [
30+
{
31+
app: 'setup',
32+
group: 'group_apps',
33+
priority: 100,
34+
items: [
35+
{ id: 'nav_marketplace_browse', type: 'url', label: 'Browse Marketplace', url: '/apps/setup/system/marketplace', icon: 'store' },
36+
],
37+
},
38+
],
39+
};
40+
41+
/** "Installed Apps" — owned by the local-install capability. */
42+
export const MARKETPLACE_INSTALLED_UI_BUNDLE = {
43+
id: 'com.objectstack.cloud-connection.marketplace-installed-ui',
44+
namespace: 'sys',
45+
version: '0.1.0',
46+
type: 'plugin',
47+
scope: 'system',
48+
name: 'Marketplace Installed UI',
49+
description: 'Setup navigation for locally-installed marketplace packages.',
50+
navigationContributions: [
51+
{
52+
app: 'setup',
53+
group: 'group_apps',
54+
priority: 110,
55+
items: [
56+
{ id: 'nav_marketplace_installed', type: 'url', label: 'Installed Apps', url: '/apps/setup/system/marketplace/installed', icon: 'package-check' },
57+
],
58+
},
59+
],
60+
};

packages/platform-objects/src/apps/setup-nav.contributions.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ import type { NavigationContribution } from '@objectstack/spec/ui';
2626

2727
const BASE_PRIORITY = 100;
2828

29+
// Marketplace entries (browse / installed) moved to
30+
// @objectstack/cloud-connection's marketplace plugins (cloud ADR-0009:
31+
// the nav lives and dies with the capability — no plugin, no entry).
2932
export const SETUP_NAV_CONTRIBUTIONS: NavigationContribution[] = [
3033
{
3134
app: 'setup',
@@ -40,8 +43,6 @@ export const SETUP_NAV_CONTRIBUTIONS: NavigationContribution[] = [
4043
group: 'group_apps',
4144
priority: BASE_PRIORITY,
4245
items: [
43-
{ id: 'nav_marketplace_browse', type: 'url', label: 'Browse Marketplace', url: '/apps/setup/system/marketplace', icon: 'store' },
44-
{ id: 'nav_marketplace_installed', type: 'url', label: 'Installed Apps', url: '/apps/setup/system/marketplace/installed', icon: 'package-check', requiresObject: 'sys_package_installation' },
4546
],
4647
},
4748
{

0 commit comments

Comments
 (0)