You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maka.apache.org by "Astro-Han (via GitHub)" <gi...@apache.org> on 2026/08/19 15:33:09 UTC
Re: [PR] feat(desktop): add managed remote Runtime Host onboarding [maka]
Astro-Han commented on code in PR #3236:
URL: https://github.com/apache/maka/pull/3236#discussion_r3814406781
##########
apps/desktop/src/main/runtime-host-pairing-journal.ts:
##########
@@ -0,0 +1,196 @@
+import { randomUUID } from 'node:crypto';
+import { join } from 'node:path';
+import {
+ decodeRemoteRuntimeHostProfile,
+ RUNTIME_HOST_ACCESS_CREDENTIAL_MAX_BYTES,
+ sameResolvedRuntimeHostProfileTarget,
+ type RemoteRuntimeHostProfile,
+ type ResolvedRuntimeHostProfile,
+} from '@maka/runtime-host/client';
+import { createFileCredentialStore } from '@maka/storage';
+
+const PAIRING_JOURNAL_SCHEMA_VERSION = 1;
+const PAIRING_JOURNAL_CREDENTIAL_SLOT = 'runtime-host-pairing-recovery';
+const PAIRING_JOURNAL_MAX_BYTES = 512 * 1024;
+const PAIRING_JOURNAL_MAX_ENTRIES = 32;
+
+export interface DesktopRuntimeHostPairingIntent {
+ readonly id: string;
+ readonly target: {
+ readonly profile: RemoteRuntimeHostProfile;
+ readonly credential: string;
+ };
+ readonly previous?: {
+ readonly profile: RemoteRuntimeHostProfile;
+ readonly credential: string;
+ };
+ readonly wasEnabled: boolean;
+}
+
+export function createDesktopRuntimeHostPairingIntent(input: {
+ readonly target: ResolvedRuntimeHostProfile;
+ readonly previous?: ResolvedRuntimeHostProfile;
+ readonly wasEnabled: boolean;
+}): DesktopRuntimeHostPairingIntent {
+ return {
+ id: randomUUID(),
+ target: requireRemoteTarget(input.target, 'pairing target'),
+ ...(input.previous
+ ? { previous: requireRemoteTarget(input.previous, 'previous pairing target') }
+ : {}),
+ wasEnabled: input.wasEnabled,
+ };
+}
+
+export function pairingIntentMatchesTarget(
+ intentTarget: DesktopRuntimeHostPairingIntent['target'],
+ target: ResolvedRuntimeHostProfile,
+): boolean {
+ return sameResolvedRuntimeHostProfileTarget(intentTarget, target);
+}
+
+export async function readDesktopRuntimeHostPairingIntents(
+ clientDataRoot: string,
+): Promise<readonly DesktopRuntimeHostPairingIntent[]> {
+ const contents = await pairingCredentialStore(clientDataRoot).getSecret(
+ PAIRING_JOURNAL_CREDENTIAL_SLOT,
+ 'runtime_host_access',
+ );
+ if (contents === null) return [];
+ if (Buffer.byteLength(contents, 'utf8') > PAIRING_JOURNAL_MAX_BYTES) {
+ throw new Error('Runtime Host pairing recovery journal exceeds its size limit');
+ }
+ try {
+ return decodePairingJournal(JSON.parse(contents));
+ } catch (error) {
+ throw new Error('Runtime Host pairing recovery journal is invalid', { cause: error });
+ }
+}
+
+export async function writeDesktopRuntimeHostPairingIntents(
+ clientDataRoot: string,
+ intents: readonly DesktopRuntimeHostPairingIntent[],
+): Promise<void> {
+ const credentials = pairingCredentialStore(clientDataRoot);
+ if (intents.length === 0) {
+ await credentials.deleteSecret(
+ PAIRING_JOURNAL_CREDENTIAL_SLOT,
+ 'runtime_host_access',
+ );
+ return;
+ }
+ const contents = JSON.stringify({
+ schemaVersion: PAIRING_JOURNAL_SCHEMA_VERSION,
+ intents,
+ });
+ if (Buffer.byteLength(contents) > PAIRING_JOURNAL_MAX_BYTES) {
+ throw new Error('Runtime Host pairing recovery journal exceeds its size limit');
+ }
+ await credentials.setSecret(
Review Comment:
**[P2] Preserve the pairing intent across power loss before mutating the profile**
Pairing recovery now stores its intent through `createFileCredentialStore`, but that store's atomic writer returns after `writeFile`/rename without syncing the temporary file or parent directory. A sudden power loss may therefore retain the later rebound profile while losing the preceding journal/credential-store rename, recreating the persisted-before-finalize state that startup cannot reconcile. Please durability-fence the shared secret writer—sync the temporary file before rename and the parent directory afterward on supported platforms—or retain a durability-fenced secret journal. Add ordering/failure-injection coverage at the owning seam if practical.
<details><summary>中文说明</summary>
这里写恢复意图后才会修改 profile,但共享 secret writer 只有写临时文件和 rename,没有在 rename 前 fsync 文件、rename 后同步父目录。突然掉电时可能保留后写的 profile,却丢失更早的 journal,从而重新出现无法恢复的 pairing 窗口。请在共享 writer 增加 durability fence,或保留有同等保证的独立 journal。
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org