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
14 changes: 12 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,20 @@ jobs:
if: steps.plan.outputs.storybook == 'true'
run: npm --workspace @maka/desktop run smoke:storybook

- name: Update stable Rust for CLI packaging
if: steps.plan.outputs.cli_package == 'true'
run: rustup update stable --no-self-update

- name: Install cargo-deny for CLI packaging
if: steps.plan.outputs.cli_package == 'true'
uses: taiki-e/install-action@fcf5432d9f50d67e37ee6e29bdb7a224ff67b4a7 # v2
with:
tool: cargo-deny@0.20.2

- name: Build CLI release candidate
if: steps.plan.outputs.cli_package == 'true'
run: npm run release:cli:pack
run: npm run release:cli:pack -- --allow-dirty

- name: Validate installed CLI release candidate
if: steps.plan.outputs.cli_package == 'true'
run: npm run release:cli:smoke
run: npm run release:cli:smoke -- packages/cli/release/*.tgz
106 changes: 106 additions & 0 deletions .github/workflows/cli-package-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,23 @@
name: CLI package validation

on:
pull_request:
paths:
- '.github/workflows/cli-package-validation.yml'
- '.github/workflows/runtime-host-peer-admission.yml'
- 'deny.toml'
- 'native/runtime-host-peer/**'
- 'package-lock.json'
- 'packages/cli/RUNTIME_HOST_PEER_*'
- 'packages/cli/src/cli-core.ts'
- 'packages/cli/src/runtime-host-cli.ts'
- 'packages/cli/src/runtime-host-peer-*'
- 'packages/cli/src/runtime-host-service-*'
- 'packages/runtime-host/src/server/peer-listener.ts'
- 'packages/runtime-host/src/transport/peer-native.ts'
- 'scripts/generate-runtime-host-peer-*'
- 'scripts/release-cli-package.mjs'
- 'scripts/smoke-release-cli-package.mjs'
workflow_call:
inputs:
source_commit:
Expand All @@ -41,8 +58,79 @@ concurrency:
group: cli-package-validation-${{ github.workflow }}-${{ github.ref }}

jobs:
peer-native:
name: Build direct-peer addon (${{ matrix.target }})
runs-on: ${{ matrix.runner }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
- runner: macos-15
target: darwin-arm64
rust_target: ''
- runner: ubuntu-24.04-arm
target: linux-arm64
rust_target: aarch64-unknown-linux-gnu.2.28
- runner: ubuntu-24.04
target: linux-x64
rust_target: x86_64-unknown-linux-gnu.2.28
- runner: windows-2025
target: win32-x64
rust_target: ''
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ inputs.source_commit || github.sha }}
persist-credentials: false
- name: Update stable Rust
run: rustup update stable --no-self-update
- name: Install the Linux baseline linker
if: startsWith(matrix.target, 'linux-')
uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2
with:
version: 0.16.0
- name: Install cargo-zigbuild
if: startsWith(matrix.target, 'linux-')
uses: taiki-e/install-action@fcf5432d9f50d67e37ee6e29bdb7a224ff67b4a7 # v2
with:
tool: cargo-zigbuild@0.23.2
- name: Build the release addon
env:
MAKA_RUNTIME_HOST_PEER_CARGO_SUBCOMMAND: ${{ matrix.rust_target && 'zigbuild' || '' }}
MAKA_RUNTIME_HOST_PEER_CARGO_TARGET: ${{ matrix.rust_target }}
run: node native/runtime-host-peer/build.mjs
- name: Enforce the Linux glibc baseline
if: startsWith(matrix.target, 'linux-')
run: |
node - <<'NODE'
const { execFileSync } = require('node:child_process');
const output = execFileSync('readelf', [
'--version-info',
'native/runtime-host-peer/target/release/maka_runtime_host_peer.node',
], { encoding: 'utf8' });
const versions = [...output.matchAll(/GLIBC_(\d+)\.(\d+)/g)].map((match) => [
Number(match[1]),
Number(match[2]),
]);
const newer = versions.find(([major, minor]) => major > 2 || (major === 2 && minor > 28));
if (newer) throw new Error(`Direct-peer addon requires GLIBC_${newer.join('.')}`);
NODE
- name: Stage the platform addon
env:
PEER_TARGET: ${{ matrix.target }}
run: node -e "const fs=require('node:fs'),p=require('node:path'); const d=p.join('peer-prebuilds',process.env.PEER_TARGET); fs.mkdirSync(d,{recursive:true}); fs.copyFileSync(p.join('native','runtime-host-peer','target','release','maka_runtime_host_peer.node'),p.join(d,'maka_runtime_host_peer.node'))"
- name: Upload the platform addon
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: runtime-host-peer-${{ matrix.target }}
path: peer-prebuilds
if-no-files-found: error
retention-days: 1

build:
name: Build immutable tarball
needs: peer-native
runs-on: ubuntu-24.04
timeout-minutes: 60
outputs:
Expand All @@ -59,7 +147,19 @@ jobs:
cache: npm
- name: Select the release npm toolchain
run: npm install --global --no-audit --no-fund "$(node -p 'require("./package.json").packageManager')"
- name: Install cargo-deny
uses: taiki-e/install-action@fcf5432d9f50d67e37ee6e29bdb7a224ff67b4a7 # v2
with:
tool: cargo-deny@0.20.2
- name: Download direct-peer addons
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: runtime-host-peer-*
path: ${{ runner.temp }}/runtime-host-peer-prebuilds
merge-multiple: true
- name: Build the release tarball once
env:
MAKA_RUNTIME_HOST_PEER_PREBUILDS: ${{ runner.temp }}/runtime-host-peer-prebuilds
run: npm run release:cli:pack
- name: Upload the immutable release candidate
id: release-candidate
Expand Down Expand Up @@ -92,6 +192,11 @@ jobs:
node: '24'
platform: linux
arch: x64
- name: Linux arm64 / Node 24
runner: ubuntu-24.04-arm
node: '24'
platform: linux
arch: arm64
- name: macOS arm64 / Node 24
runner: macos-15
node: '24'
Expand Down Expand Up @@ -128,6 +233,7 @@ jobs:

eval:
name: Validate installed CLI Eval
if: github.event_name != 'pull_request'
needs: build
runs-on: ubuntu-24.04
timeout-minutes: 30
Expand Down
83 changes: 22 additions & 61 deletions .github/workflows/runtime-host-peer-admission.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,25 @@ on:
pull_request:
paths:
- '.github/workflows/runtime-host-peer-admission.yml'
- 'deny.toml'
- 'native/runtime-host-peer/**'
- 'packages/cli/RUNTIME_HOST_PEER_DEPENDENCIES.rust.tsv'
- 'packages/cli/RUNTIME_HOST_PEER_THIRD_PARTY_NOTICES.txt'
- 'scripts/generate-runtime-host-peer-dependencies.mjs'
- 'scripts/generate-runtime-host-peer-notices.mjs'
- 'packages/runtime-host/src/transport/peer-native.ts'
- 'packages/runtime-host/src/server/peer-listener.ts'
push:
branches:
- main
paths:
- '.github/workflows/runtime-host-peer-admission.yml'
- 'deny.toml'
- 'native/runtime-host-peer/**'
- 'packages/cli/RUNTIME_HOST_PEER_DEPENDENCIES.rust.tsv'
- 'packages/cli/RUNTIME_HOST_PEER_THIRD_PARTY_NOTICES.txt'
- 'scripts/generate-runtime-host-peer-dependencies.mjs'
- 'scripts/generate-runtime-host-peer-notices.mjs'
- 'packages/runtime-host/src/transport/peer-native.ts'
- 'packages/runtime-host/src/server/peer-listener.ts'

Expand All @@ -42,16 +52,9 @@ concurrency:

jobs:
test:
name: ${{ matrix.os }}
runs-on: ${{ matrix.os }}
name: quality
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
Expand All @@ -67,58 +70,16 @@ jobs:
- name: Lint the native peer
working-directory: native/runtime-host-peer
run: cargo clippy --locked --all-targets -- -D warnings
- name: Install cargo-deny
uses: taiki-e/install-action@fcf5432d9f50d67e37ee6e29bdb7a224ff67b4a7 # v2
with:
tool: cargo-deny@0.20.2
- name: Check Cargo dependency inventory
run: npm run check:runtime-host-peer-dependencies
- name: Check Cargo dependency licenses
run: cargo deny --manifest-path native/runtime-host-peer/Cargo.toml --locked --exclude-dev check licenses
- name: Check Cargo dependency notices
run: npm run check:runtime-host-peer-notices
- name: Test the native peer
working-directory: native/runtime-host-peer
run: cargo test --locked
- name: Build the Node addon
run: node native/runtime-host-peer/build.mjs
- name: Exercise the Node boundary
shell: bash
run: |
node <<'NODE'
const { mkdtempSync, rmSync } = require('node:fs');
const { tmpdir } = require('node:os');
const { join, resolve } = require('node:path');
const addon = require(resolve('native/runtime-host-peer/target/debug/maka_runtime_host_peer.node'));
void (async () => {
const directory = mkdtempSync(join(tmpdir(), 'maka-peer-'));
const server = addon.startPeerEndpoint({
keyPath: join(directory, 'server.key'),
listenAddresses: ['/ip4/127.0.0.1/udp/0/quic-v1'],
});
const client = addon.startPeerEndpoint({
keyPath: join(directory, 'client.key'),
listenAddresses: ['/ip4/127.0.0.1/udp/0/quic-v1'],
});
try {
if (!server.peerId || server.listenAddresses.length === 0) {
throw new Error('native peer endpoint did not become ready');
}
const accepted = server.accept();
const outbound = await client.connect({
peerId: server.peerId,
routeHints: server.listenAddresses,
directDeadlineMs: 5_000,
});
const inbound = await accepted;
if (!inbound) throw new Error('native peer endpoint did not accept the stream');
await outbound.write(Buffer.from('ping'));
const request = await inbound.read();
if (!request || request.toString() !== 'ping') {
throw new Error('native peer endpoint received the wrong request');
}
await inbound.write(Buffer.from('pong'));
const response = await outbound.read();
if (!response || response.toString() !== 'pong') {
throw new Error('native peer endpoint received the wrong response');
}
await Promise.all([outbound.close(), inbound.close()]);
} finally {
await Promise.allSettled([client.close(), server.close()]);
rmSync(directory, { recursive: true, force: true });
}
})().catch((error) => {
console.error(error);
process.exitCode = 1;
});
NODE
36 changes: 36 additions & 0 deletions deny.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

[graph]
targets = [
"aarch64-apple-darwin",
"aarch64-unknown-linux-gnu",
"x86_64-pc-windows-msvc",
"x86_64-unknown-linux-gnu",
]

[licenses]
allow = [
"Apache-2.0",
"BSD-2-Clause",
"BSD-3-Clause",
"ISC",
"MIT",
"Unicode-3.0",
"Zlib",
]
confidence-threshold = 0.8
4 changes: 2 additions & 2 deletions docs/cli-npm-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ package owner or recovery access as part of that change.

2. Confirm the created run uses `v<version>`. The workflow requires its GitHub ref, checkout, product tag, Release, source commit, and npm provenance to identify that one tag commit, and requires the commit to remain an ancestor of `main`.
3. Wait for the reusable package validation jobs to pass. They build one tarball and validate the
installed CLI on Linux x64, macOS arm64, and Windows x64, plus real Harbor and Pier Docker cells
on Linux x64.
installed CLI on Linux x64/arm64, macOS arm64, and Windows x64, plus real Harbor and Pier
Docker cells on Linux x64.
4. Review and approve the `npm-release` Environment deployment.
5. Record the successful Stage workflow run ID, run attempt, source commit, version, and staged
artifact checksum from the run summary and `cli-staged-release-<attempt>` artifact.
Expand Down
2 changes: 1 addition & 1 deletion docs/cli-npm-release.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ authentication and disallow tokens**,然后撤销不再使用的 publish token
```

2. 确认新建的 run 使用 `v<version>`。workflow 要求其 GitHub ref、checkout、产品 tag、Release、source commit 和 npm provenance 全部指向这一个 tag commit,并要求该 commit 仍是 `main` 的 ancestor;
3. 等待可复用 package validation jobs 全部通过。它们只构建一个 tarball,并在 Linux x64、
3. 等待可复用 package validation jobs 全部通过。它们只构建一个 tarball,并在 Linux x64/arm64
macOS arm64、Windows x64 上验证安装态 CLI,在 Linux x64 上运行真实 Harbor 和 Pier
Docker cell;
4. 审查并批准 `npm-release` Environment deployment;
Expand Down
31 changes: 30 additions & 1 deletion docs/runtime-host-remote-access.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

[简体中文](./runtime-host-remote-access.zh-CN.md)

Maka Desktop, TUI, and CLI can connect to a Runtime Host through TLS, SSH, or explicitly enabled plaintext WebSocket.
Maka Desktop, TUI, and CLI can connect to a Runtime Host through TLS, SSH, or explicitly enabled plaintext WebSocket. The CLI and TUI also support the experimental direct-peer transport described below.

## Set up a Linux or macOS Host

Expand Down Expand Up @@ -102,6 +102,35 @@ ready; failure restores the previous service.

## Choose a connection method

### Experimental direct peer

The released CLI includes the native direct-peer transport for CLI and TUI use; the Host does not
need Rust or a source checkout. Desktop support is not part of this milestone. After managed setup,
enable it against the exact service target printed by setup:

```sh
maka runtime-host service peer enable \
--expected-service-id '<serviceId>' \
--expected-root-path '<rootPath>' \
--expected-root-id '<rootId>'

maka runtime-host service peer descriptor \
--expected-service-id '<serviceId>' \
--expected-root-path '<rootPath>' \
--expected-root-id '<rootId>'
```

The descriptor contains the PeerId, Root ID, and candidate routes, but never an access credential.
Use those values with `runtime-host profile set --peer-id ... --peer-route ...`; supply the
credential created by setup through `MAKA_RUNTIME_HOST_ACCESS_CREDENTIAL`. Disable and re-enable
preserve the PeerId and listener settings; `peer rotate` intentionally changes the PeerId, and
service uninstall removes its key while retaining the State Root. Pass
`peer enable --clear-coordination-relays` to remove every configured coordination relay.

This direct-only path is experimental and may fail on restrictive NAT or UDP-blocked networks. It
does not replace an existing TLS, SSH, or overlay-network fallback and does not use a public relay
unless one is explicitly configured with `peer enable --coordination-relay`.

### Direct TLS

Use TLS for a stable network endpoint:
Expand Down
Loading
Loading