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
37 changes: 18 additions & 19 deletions capsules/home-cli/browser/home-cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,7 @@ globalThis.addEventListener?.("pagehide", () => {
setRuntimeTerminalMode(false);
boot().catch((error) => {
console.error("Home CLI terminal could not start", error);
showFallback("Home CLI could not start. Return to the Desktop and try again.", {
allowDesktopRecovery: true,
allowRefresh: true,
focusDesktopRecovery: true,
includeRetainedTerminalOutput: true,
});
showTerminalStartFailure(error, "Home CLI could not start. Return to the Desktop and try again.");
});

async function boot() {
Expand Down Expand Up @@ -441,12 +436,7 @@ function reattachHomeCliTerminal(message = "") {
globalThis.setTimeout?.(() => {
startRuntimeTerminal().catch((error) => {
console.error("Home CLI could not restart", error);
showFallback("Home CLI could not reconnect. Return to the Desktop and try again.", {
allowDesktopRecovery: true,
allowRefresh: true,
focusDesktopRecovery: true,
includeRetainedTerminalOutput: true,
});
showTerminalStartFailure(error, "Home CLI could not reconnect. Return to the Desktop and try again.");
});
}, 0);
}
Expand All @@ -458,12 +448,19 @@ function retryHomeCliTerminalFromFallback() {
showFallback("Starting Home CLI terminal...", { includeRetainedTerminalOutput: false });
startRuntimeTerminal().catch((error) => {
console.error("Home CLI retry failed", error);
showFallback("Home CLI could not start. Return to the Desktop and try again.", {
allowDesktopRecovery: true,
allowRefresh: true,
focusDesktopRecovery: true,
includeRetainedTerminalOutput: true,
});
showTerminalStartFailure(error, "Home CLI could not start. Return to the Desktop and try again.");
});
}

function showTerminalStartFailure(error, message) {
const refused = error?.status === 403;
showFallback(refused
? "Runtime refused web terminal access. The host operator can check developer mode and guest registration. Return to the Desktop."
: message, {
allowDesktopRecovery: true,
allowRefresh: !refused,
focusDesktopRecovery: true,
includeRetainedTerminalOutput: true,
});
}

Expand Down Expand Up @@ -687,7 +684,9 @@ async function fetchJson(url, init = {}) {
const response = await fetch(url, init);
if (!response.ok) {
const detail = await response.text().catch(() => "");
throw new Error(detail || `request failed: ${response.status}`);
const error = new Error(detail || `request failed: ${response.status}`);
error.status = response.status;
throw error;
}
return response.json();
}
Expand Down
15 changes: 15 additions & 0 deletions docs/COMMAND_MATRIX.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,21 @@ target.
| Updates | `elastos update`, `elastos upgrade` | `upgrade` dispatches to the same update handler. Discovery may use Carrier or explicit gateways, but no local runtime is required. |
| Offline principal-root maintenance | hidden `elastos principal-root-migrate`, hidden `elastos principal-root-upgrade` | Operates on an explicit data directory. The Runtime must be offline and the command requires explicit backup inputs. |

The host operator controls web terminal access with
`elastos config set developer_mode true` and
`elastos config set developer_mode false`. Runtime stores this boolean in
`config.toml` in its data folder. The default is off. Home and apps use Runtime
routes and app storage roots; the host CLI owns this setting. The existing
`dev_mode` setting controls capsule signature checks separately.

Runtime refuses all web terminal routes with HTTP 403 while developer mode is
off or guest registration is enabled. This includes signed-in owners. A refused
start request creates no host process. The next request uses the current
setting. Runtime checks existing web terminal sessions each second and closes
them when the policy refuses access. It also checks the policy before each
input message. Home CLI shows a refusal with host operator guidance and a
Return to Desktop button. The host CLI `elastos home` remains available.

The host operator sets accepted public gateway authorities with
`elastos config set gateway_allowed_hosts '["home.example.com"]'`, then restarts
the gateway. Each authority includes its port when it uses a non-default port.
Expand Down
7 changes: 6 additions & 1 deletion elastos/crates/elastos-server/src/api/gateway.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1212,14 +1212,19 @@ fn gateway_router_with_api_url(state: GatewayState, gateway_api_url: String) ->
"/apps/:app/*path",
get(super::browser_capsules::serve_browser_app_asset),
)
.with_state(state)
.with_state(state.clone())
.layer(Extension(TrustedGatewayApiUrl(Arc::from(gateway_api_url))))
.layer(axum::middleware::from_fn(refuse_content_api_resources))
.layer(axum::middleware::from_fn_with_state(
admission_state,
gateway_frontdoor::gateway_admission,
))
.layer(Extension(frontdoor))
// Terminal policy also gates browser preflight before its early response.
.layer(axum::middleware::from_fn_with_state(
state.data_dir.clone(),
home_cli_terminal_access,
))
}

// ---------------------------------------------------------------------------
Expand Down
Loading
Loading