From a58846c525c9e632f80d6129398b0d354eabee21 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 5 Nov 2026 12:00:52 +0000 Subject: [PATCH 1/3] feat(console): the install result says when a package was installed without a protocol compatibility check The install door answers data.protocolCheckSkipped when its protocol handshake admitted the package unchecked (no engines.protocol, or a range it cannot read). The package page's Install result, the catalog's org install message and Setup > Packages > Import now draw it as a caution line, in the reader's locale, from the notice's facts. Claude-Session: https://claude.ai/code/session_01L6bhgWZ1wrAZ2ocZovnByy Co-authored-by: Claude --- ...6-install-result-protocol-check-skipped.md | 13 ++ .../marketplace/MarketplacePackagePage.tsx | 19 ++- .../console/marketplace/MarketplacePage.tsx | 9 + .../marketplace/ProtocolCheckSkippedNote.tsx | 22 +++ ...gePage.protocolCheckSkipped-30326.test.tsx | 155 ++++++++++++++++++ ...InstallProtocolCheckSkipped-30326.test.tsx | 133 +++++++++++++++ .../protocolCheckSkipped-30326.test.ts | 54 ++++++ .../src/console/marketplace/marketplaceApi.ts | 9 + .../marketplace/protocolCheckSkipped.ts | 74 +++++++++ ....importProtocolCheckSkipped-30326.test.tsx | 101 ++++++++++++ .../src/views/metadata-admin/PackagesPage.tsx | 10 +- ui/packages/i18n/src/locales/ar.ts | 4 + ui/packages/i18n/src/locales/de.ts | 4 + ui/packages/i18n/src/locales/en.ts | 5 + ui/packages/i18n/src/locales/es.ts | 4 + ui/packages/i18n/src/locales/fr.ts | 4 + ui/packages/i18n/src/locales/ja.ts | 4 + ui/packages/i18n/src/locales/ko.ts | 4 + ui/packages/i18n/src/locales/pt.ts | 4 + ui/packages/i18n/src/locales/ru.ts | 4 + ui/packages/i18n/src/locales/zh.ts | 5 + 21 files changed, 637 insertions(+), 4 deletions(-) create mode 100644 .changeset/30326-install-result-protocol-check-skipped.md create mode 100644 ui/packages/app-shell/src/console/marketplace/ProtocolCheckSkippedNote.tsx create mode 100644 ui/packages/app-shell/src/console/marketplace/__tests__/MarketplacePackagePage.protocolCheckSkipped-30326.test.tsx create mode 100644 ui/packages/app-shell/src/console/marketplace/__tests__/MarketplacePage.orgInstallProtocolCheckSkipped-30326.test.tsx create mode 100644 ui/packages/app-shell/src/console/marketplace/__tests__/protocolCheckSkipped-30326.test.ts create mode 100644 ui/packages/app-shell/src/console/marketplace/protocolCheckSkipped.ts create mode 100644 ui/packages/app-shell/src/views/metadata-admin/PackagesPage.importProtocolCheckSkipped-30326.test.tsx diff --git a/.changeset/30326-install-result-protocol-check-skipped.md b/.changeset/30326-install-result-protocol-check-skipped.md new file mode 100644 index 00000000000..76bed3f0ee4 --- /dev/null +++ b/.changeset/30326-install-result-protocol-check-skipped.md @@ -0,0 +1,13 @@ +--- +'@object-ui/app-shell': patch +'@object-ui/i18n': patch +--- + +feat(console): the install result says when a package was installed without a protocol compatibility check + +Clause-②: yes (widening) +Metadata-protocol: none + +- **What the administrator now reads.** `POST /api/v1/marketplace/install-local` answers `data.protocolCheckSkipped` when its protocol handshake admitted the package without checking it: the package declares no `engines.protocol` (`no-range`), or a range the runtime cannot read (`unparsed-range`). The three Console surfaces that show an install result now draw it as a caution line under the success sentence: the package page's Install result, the catalog's organization install message, and Setup → Packages → Import. The line names the package, the platform protocol it was installed under and, for `unparsed-range`, the range it declared, in the reader's locale. A `reason` this Console does not know shows the server's own `message`. An install whose range was checked shows nothing new. +- **Types.** `LocalManagedInstallResult` and `LocalUnmanagedInstallResult` gain the optional `protocolCheckSkipped`. +- **New strings.** `@object-ui/i18n` gains `marketplace.install.protocolCheckSkipped.noRange` and `.unparsedRange` in all 10 locales. diff --git a/ui/packages/app-shell/src/console/marketplace/MarketplacePackagePage.tsx b/ui/packages/app-shell/src/console/marketplace/MarketplacePackagePage.tsx index efcd58c8237..4c470452b40 100644 --- a/ui/packages/app-shell/src/console/marketplace/MarketplacePackagePage.tsx +++ b/ui/packages/app-shell/src/console/marketplace/MarketplacePackagePage.tsx @@ -81,6 +81,8 @@ import { type CloudInstallationInfo, } from './marketplaceApi.js'; import { useDependencyMissingText } from './dependencyMissing.js'; +import { useProtocolCheckSkippedText } from './protocolCheckSkipped.js'; +import { ProtocolCheckSkippedNote } from './ProtocolCheckSkippedNote.js'; import { getCloudBase, getRuntimeConfig, isMarketplaceEnabled } from '../../runtime-config.js'; import { emitMetadataRefresh } from '../../assistant/assistantBus.js'; import { useMetadata } from '../../providers/MetadataProvider.js'; @@ -147,6 +149,7 @@ export function MarketplacePackagePage() { const { isAdmin, isResolved } = useWorkspaceAdminStatus(); const { t, language } = useObjectTranslation(); const dependencyMissingText = useDependencyMissingText(); + const protocolCheckSkippedText = useProtocolCheckSkippedText(); // Dates and numbers on this surface read the display locale; a bare // `toLocale*()` call used the MACHINE's locale (objectui#9909). const displayLocale = useDisplayLocale(); @@ -266,6 +269,9 @@ export function MarketplacePackagePage() { message: string; unmanaged?: { strippedLocks: LocalInstallStrippedLock[] }; credentials?: { packageId: string; note?: string }; + // objectstack#30326 — the install answer's `protocolCheckSkipped`, drawn: + // installed, but its platform protocol range was not checked. + protocolNote?: string; } | null>(null); // ADR-0131 D6 — the install modes the package's latest manifest declares, // read from the manifest install-local judges, and the operator's pick among @@ -600,6 +606,10 @@ export function MarketplacePackagePage() { try { const result = await installLocal({ packageId, ...(installMode ? { installMode } : {}) }); const name = data?.package ? localizePackage(data.package as any, language).displayName : result.manifestId; + // objectstack#30326 — every success answer can say the package was + // admitted with its protocol range unchecked; each note below carries it. + const protocolNote = protocolCheckSkippedText(result) ?? undefined; + const withProtocolNote = protocolNote ? { protocolNote } : {}; // An unmanaged copy (ADR-0131 D6): the package's metadata is this // runtime's own from now on, in the base the answer names; the answer // lists every protection lock the copy dropped, with the package's reason. @@ -613,6 +623,7 @@ export function MarketplacePackagePage() { ok: true, message: t('marketplace.install.unmanagedSuccess', { version: result.version, name, base: result.targetPackageId }), unmanaged: { strippedLocks: result.strippedLocks }, + ...withProtocolNote, }); emitMetadataRefresh(); return; @@ -628,8 +639,8 @@ export function MarketplacePackagePage() { // and the page says when the app will appear. if (!result.hotLoaded) { setLocalResult(ignoredCopy - ? { ok: false, message: t('marketplace.install.unmanagedIgnored', { name }) } - : { ok: true, message: t('marketplace.install.localLoadsAtRestart', { version: result.version, name }) }); + ? { ok: false, message: t('marketplace.install.unmanagedIgnored', { name }), ...withProtocolNote } + : { ok: true, message: t('marketplace.install.localLoadsAtRestart', { version: result.version, name }), ...withProtocolNote }); return; } try { @@ -638,11 +649,12 @@ export function MarketplacePackagePage() { // Non-fatal: the install succeeded; the app list will refresh on next navigation. } setLocalResult(ignoredCopy - ? { ok: false, message: t('marketplace.install.unmanagedIgnored', { name }) } + ? { ok: false, message: t('marketplace.install.unmanagedIgnored', { name }), ...withProtocolNote } : { ok: true, message: t('marketplace.install.localSuccess', { version: result.version, name }), credentials: { packageId: result.manifestId, note: result.credentialNote }, + ...withProtocolNote, }); emitMetadataRefresh(); } catch (e: any) { @@ -995,6 +1007,7 @@ export function MarketplacePackagePage() { {localResult.ok ?