Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions COMPATIBILITY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Compatibility Contract

## Candidate 1.6.203 / bridge 0.2.5

Adds restricted-Key discovery against the existing Engine361 typed contract.
Default discovery remains ordinary `apiKey`; use `apiKeyRestricted` explicitly.
The assembled Server also needs Engine363 for accurate External Service previews
and the retained native ServiceIndex cleanup repair. Publication and runtime acceptance remain pending.

## Web Console 1.6.202 / bridge 0.2.4 published

The matching typed workflows require Engine 0.183.361 and the installed audit
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ Rancher 1.6 ecosystem. It is not affiliated with Rancher Labs or SUSE.
This fork of [`rancher/ui`](https://github.com/rancher/ui) preserves upstream
history, authorship, licenses, and dependency notices.

## In development: 1.6.203 / bridge 0.2.5

Restricted API Keys gain the same name-based discovery and audit-reference flow
as ordinary Keys. Select `apiKeyRestricted` explicitly; the default searches
`apiKey` only. This is partial family coverage, not a merged search or complete
frontend automation. Confirmation errors gain clear permission guidance in all
thirteen locales, and follow-redirects uses its official 1.16.2 patch. Publication
and designated QA acceptance remain pending.

## Current component

[Web Console **1.6.202** / bridge **0.2.4**](https://github.com/PastureStack/web-console/releases/tag/1.6.202)
Expand Down
4 changes: 2 additions & 2 deletions app/components/modal-confirm-ai-upgrade/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { computed } from '@ember/object';
import { alias } from '@ember/object/computed';
import { service } from '@ember/service';
import ModalBase from 'lacsso/components/modal-base';
import { resourceReviewLabels } from 'ui/utils/ai-resource-review-labels';
import { resourceReviewLabels, resourceConfirmationErrorKey } from 'ui/utils/ai-resource-review-labels';
import { createCatalogHumanForm } from 'ui/utils/ai-catalog-human-form';
import { observer } from '@ember/object';

Expand Down Expand Up @@ -140,7 +140,7 @@ export default ModalBase.extend({
return this.get('commands').confirmPendingPlan().then((result) => {
if (this.isDestroyed || this.isDestroying) { return; }
if (result.status !== 'succeeded' || result.confirmationState !== 'approved') {
this.set('errors', [this.get('intl').t(result.code === 'STALE_REFERENCE' || result.code === 'CONTEXT_CHANGED' ? 'webmcp.stale' : 'webmcp.failed')]);
this.set('errors', [this.get('intl').t(resourceConfirmationErrorKey(result.code))]);
return;
}
this.set('approved', true);
Expand Down
4 changes: 2 additions & 2 deletions app/utils/ai-command-contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const catalogAnswers = {type: 'array', maxItems: 100, items: schema({questionRef
value: {type: ['string', 'number', 'boolean'], minLength: 0, maxLength: 4096, minimum: -Number.MAX_SAFE_INTEGER, maximum: Number.MAX_SAFE_INTEGER}, resourceRef: string('An authorized resourceRef, or a same-session serviceRef for service questions. Never send a raw resource ID.')}, ['questionRef']),
description: 'Typed answers only. Each questionRef accepts exactly one value or resourceRef. For an optional reference, value "" explicitly selects no resource. Human-only inputs must be completed in the console; never send a password or secret value.'};
const auditFilters = schema({
keyRef: string('Optional API Key resourceRef returned by find_resources; never supply a raw credential ID.'),
keyRef: string('Optional apiKey or apiKeyRestricted resourceRef returned by find_resources in api-keys with the intended resourceType; never supply a raw credential ID.'),
environmentRef: string('Optional visible project resourceRef; current environment is used by default.'),
environmentScope: {...string('Use current by default. all-visible explicitly requests only environments allowed by the native audit owner.'), enum: ['current', 'all-visible']},
from: string('Range start, inclusive, RFC3339 with timezone; supply together with to.', 64),
Expand All @@ -28,7 +28,7 @@ const auditFilters = schema({
});
export const COMMANDS = Object.freeze([
{name: 'list_capabilities', description: 'List the closed resource families, their implementation coverage and current read availability. Pending adapters are not implemented. Does not change environment or expose credentials.', inputSchema: schema({})},
{name: 'find_resources', description: 'Find visible resource metadata in a named family. resourceType defaults to the first type listed by list_capabilities. Return all same-name candidates; never select the first automatically. In catalog, find catalogTemplate by name first, then list catalogTemplateVersion with its resourceRef as parentRef and no query. Version metadata does not establish compatibility. Parent and cursor references must be reused unchanged.',
{name: 'find_resources', description: 'Find visible resource metadata in a named family. resourceType defaults to the first type listed by list_capabilities. In api-keys, select apiKey for legacy Keys or apiKeyRestricted for restricted or expiring Keys; the default searches apiKey only, without combining kinds. Return all same-name candidates within the selected type; never select the first automatically. In catalog, find catalogTemplate by name first, then list catalogTemplateVersion with its resourceRef as parentRef and no query. Version metadata does not establish compatibility. Parent and cursor references must be reused unchanged.',
inputSchema: schema({family: {...string('Family from list_capabilities.'), enum: RESOURCE_FAMILIES.map((item) => item.name)},
resourceType: {...string('Optional type within that family, from list_capabilities.'), enum: RESOURCE_TYPES},
query: string('Optional resource name words.'), parentRef: string('Optional resourceRef of the parent type listed by list_capabilities.'),
Expand Down
4 changes: 3 additions & 1 deletion app/utils/ai-resource-registry.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions app/utils/ai-resource-review-labels.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ const STATES = {active: 'formPorts.preflight.state.active', inactive: 'formPorts
removed: 'webmcp.removedState', mixed: 'webmcp.mixedState', empty: 'webmcp.emptyStack',
start: 'action.start', stop: 'action.stop', restart: 'action.restart', remove: 'action.remove'};

// Only an already sanitized public code selects fixed human guidance.
export function resourceConfirmationErrorKey(code) {
if ( code === 'FORBIDDEN' ) { return 'webmcp.forbidden'; }
return ['CONFLICT', 'SESSION_REQUIRED', 'STALE_REFERENCE', 'STALE_REF', 'CONTEXT_CHANGED'].includes(code) ? 'webmcp.stale' : 'webmcp.failed';
}

// UI text only. Keep the immutable plan and its exact JSON program values intact.
export function resourceReviewLabels(plan, translate) {
const text = (key) => String(translate(key || 'generic.unknown'));
Expand Down
4 changes: 2 additions & 2 deletions bridge/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion bridge/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pasturestack/webmcp-bridge",
"version": "0.2.4",
"version": "0.2.5",
"private": true,
"type": "module",
"description": "Isolated stdio adapter for the shared PastureStack command contract",
Expand Down
2 changes: 1 addition & 1 deletion bridge/server.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ try {
const path = process.env.PASTURESTACK_BRIDGE_CONFIG;
if (!path) throw new SetupError('CONFIG_REQUIRED');
const bridge = await createBridge(await loadConfig(path));
const server = new Server({name: 'pasturestack-webmcp-bridge', version: '0.2.4'}, {
const server = new Server({name: 'pasturestack-webmcp-bridge', version: '0.2.5'}, {
capabilities: {tools: {}},
instructions: 'Use names and returned opaque references. Never guess IDs. A human must approve change plans in the console. Rejected calls must be repaired only as directed; never evade permissions. Accepted/running is not success. Read the existing operation until verifiedResult=true.',
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "@pasturestack/web-console",
"version": "1.6.202",
"version": "1.6.203",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@pasturestack/web-console",
"version": "1.6.202",
"version": "1.6.203",
"license": "Apache-2.0",
"dependencies": {
"sass": "1.103.1"
Expand Down Expand Up @@ -12697,9 +12697,9 @@
}
},
"node_modules/follow-redirects": {
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.1.tgz",
"integrity": "sha512-FNvFGzoMLWmE6Yj9spb/zjd7yiNCHiAW9/Tg9CXrQ8wuu32HtlJOwWO11OJafl5FfY3DxTdQ0vj42zU1kvv5jg==",
"version": "1.16.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.2.tgz",
"integrity": "sha512-/kVP2U8z596Ia0gwFrwyIeo74ta5aVmSeU1FfAUMAmcEP5EP7zydmag3SLiN64NaRKef3lxsq7i/g7ltJQDGow==",
"dev": true,
"funding": [
{
Expand Down
40 changes: 40 additions & 0 deletions docs/releases/web-console-1.6.203.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Web Console 1.6.203 / bridge 0.2.5

Source candidate; publication and designated workflow acceptance remain pending.

The shared API Key resource family now includes `apiKeyRestricted`. Both browser
WebMCP and the stdio bridge can find a restricted Key by its visible name, use
the returned opaque reference and query its authorized audit metadata. The Engine
already supports this native type; no credential manager or policy is widened.

The family remains partial. Omitting `resourceType` searches ordinary `apiKey`
resources; choose `apiKeyRestricted` for restricted Keys. The two collections are
not silently merged. A same-name match never authorizes an arbitrary target,
owner denials remain denials, and mismatched response types are rejected.

Four causal regression cases cover both transports, explicit type selection,
owner denial and incorrect response types. The two directly affected resource
and audit suites pass 39 cases. This does not establish runtime or all-frontend
acceptance. Token/MFA/session and human-confirmation protections are unchanged.

This patch requires the existing Engine 0.183.361 typed resource contract. The
matching Server also includes Engine 0.183.363, retaining ServiceIndex cleanup
and correcting External Service review before values.
Both opt-in defaults and ordinary Full/legacy API behavior remain unchanged.

## Clear confirmation errors and official dependency fix

Rejected human approvals now use the existing alert style with a clear account/Key
permission message in all thirteen locales. Conflict, changed-session and stale
references prompt a new preview. Unknown failures remain generic; arbitrary server
messages and private payloads are never displayed. Authorization and the saving
lock/finally lifecycle are unchanged. Six focused cases cover the public error
contract, safe text, cleanup and actual locale parsing.

The build dependency follow-redirects is pinned to official 1.16.2 for
[CVE-2026-116689](https://github.com/advisories/GHSA-mrwp-f3q8-3g9p). Real loopback
cases retain same-origin behavior and stop cross-realm sensitive headers from
following cross-origin redirects. The npm12 audit parser separately recognizes
lock-proven aliases and exact duplicate causes while retaining distinct advisory
source/range, raw findings and all existing High/Critical/review-expiry gates.
This is not a new vulnerability exception or a claim of zero Moderate findings.
10 changes: 5 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pasturestack/web-console",
"version": "1.6.202",
"version": "1.6.203",
"private": true,
"description": "PastureStack browser console for the compatible control platform.",
"repository": {
Expand Down Expand Up @@ -39,7 +39,7 @@
"ember-cli-htmlbars": "7.0.1",
"engine.io": "6.6.10",
"fast-uri": "3.1.9",
"follow-redirects": "1.16.1",
"follow-redirects": "1.16.2",
"@xmldom/xmldom": "0.9.12",
"js-yaml": "4.3.2",
"morgan": "1.12.1",
Expand Down
4 changes: 2 additions & 2 deletions scripts/check-modernization-blockers
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ with open('package.json', encoding='utf-8') as f:
print(json.load(f).get('version', ''))
PY
)
if [[ "$version" != "1.6.202" ]]; then
echo "UNEXPECTED_UI_ARTIFACT_VERSION version=$version expected=1.6.202"
if [[ "$version" != "1.6.203" ]]; then
echo "UNEXPECTED_UI_ARTIFACT_VERSION version=$version expected=1.6.203"
failures=$((failures + 1))
fi

Expand Down
Loading
Loading