@amalgm/shell 0.1.162 → 0.1.164-main.34182640231

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/PURPOSE.md +163 -17
  2. package/README.md +74 -11
  3. package/config/releases/trust/runtime/main.root.json +84 -0
  4. package/config/releases/trust/runtime/preview.root.json +84 -0
  5. package/dist/authorization/recovery-host.d.ts +1 -0
  6. package/dist/authorization/recovery-host.js +2 -3
  7. package/dist/authorization/recovery-host.js.map +1 -1
  8. package/dist/boot.js +28 -20
  9. package/dist/boot.js.map +1 -1
  10. package/dist/cli-arguments.d.ts +8 -0
  11. package/dist/cli-arguments.js +47 -0
  12. package/dist/cli-arguments.js.map +1 -0
  13. package/dist/cli.d.ts +6 -4
  14. package/dist/cli.js +91 -73
  15. package/dist/cli.js.map +1 -1
  16. package/dist/compose.js +4 -3
  17. package/dist/compose.js.map +1 -1
  18. package/dist/content-cache-index.js +2 -2
  19. package/dist/content-cache-index.js.map +1 -1
  20. package/dist/detection/runtime.js +2 -2
  21. package/dist/detection/runtime.js.map +1 -1
  22. package/dist/development/profile.d.ts +27 -0
  23. package/dist/development/profile.js +142 -0
  24. package/dist/development/profile.js.map +1 -0
  25. package/dist/entity-apply-host.js +2 -2
  26. package/dist/entity-apply-host.js.map +1 -1
  27. package/dist/entity-apply-store.d.ts +2 -1
  28. package/dist/entity-apply-store.js +52 -37
  29. package/dist/entity-apply-store.js.map +1 -1
  30. package/dist/files-register-host.d.ts +1 -0
  31. package/dist/files-register-host.js +1 -0
  32. package/dist/files-register-host.js.map +1 -1
  33. package/dist/installation/environment.d.ts +30 -0
  34. package/dist/installation/environment.js +28 -0
  35. package/dist/installation/environment.js.map +1 -0
  36. package/dist/installation/lease.d.ts +6 -0
  37. package/dist/installation/lease.js +28 -0
  38. package/dist/installation/lease.js.map +1 -0
  39. package/dist/installation/ownership.d.ts +30 -0
  40. package/dist/installation/ownership.js +156 -0
  41. package/dist/installation/ownership.js.map +1 -0
  42. package/dist/installation/selection.d.ts +8 -0
  43. package/dist/installation/selection.js +29 -0
  44. package/dist/installation/selection.js.map +1 -0
  45. package/dist/machine-host.d.ts +27 -5
  46. package/dist/machine-host.js +244 -96
  47. package/dist/machine-host.js.map +1 -1
  48. package/dist/main.js +56 -2
  49. package/dist/main.js.map +1 -1
  50. package/dist/platform-product-host.d.ts +9 -9
  51. package/dist/platform-product-host.js +17 -17
  52. package/dist/platform-product-host.js.map +1 -1
  53. package/dist/platform-tools.d.ts +4 -3
  54. package/dist/platform-tools.js +34 -37
  55. package/dist/platform-tools.js.map +1 -1
  56. package/dist/process-lifecycle.d.ts +6 -0
  57. package/dist/process-lifecycle.js +42 -0
  58. package/dist/process-lifecycle.js.map +1 -0
  59. package/dist/pty-host.d.ts +1 -1
  60. package/dist/pty-host.js +70 -21
  61. package/dist/pty-host.js.map +1 -1
  62. package/dist/runtime-command-host.d.ts +7 -0
  63. package/dist/runtime-command-host.js +49 -13
  64. package/dist/runtime-command-host.js.map +1 -1
  65. package/dist/service/adapter.d.ts +36 -0
  66. package/dist/service/adapter.js +24 -0
  67. package/dist/service/adapter.js.map +1 -0
  68. package/dist/service/cli.d.ts +8 -0
  69. package/dist/service/cli.js +237 -0
  70. package/dist/service/cli.js.map +1 -0
  71. package/dist/service/control.d.ts +38 -0
  72. package/dist/service/control.js +68 -0
  73. package/dist/service/control.js.map +1 -0
  74. package/dist/service/index.d.ts +9 -0
  75. package/dist/service/index.js +10 -0
  76. package/dist/service/index.js.map +1 -0
  77. package/dist/service/keepalive.d.ts +18 -0
  78. package/dist/service/keepalive.js +418 -0
  79. package/dist/service/keepalive.js.map +1 -0
  80. package/dist/service/launchd.d.ts +9 -0
  81. package/dist/service/launchd.js +105 -0
  82. package/dist/service/launchd.js.map +1 -0
  83. package/dist/service/owner.d.ts +4 -0
  84. package/dist/service/owner.js +14 -0
  85. package/dist/service/owner.js.map +1 -0
  86. package/dist/service/portable.d.ts +10 -0
  87. package/dist/service/portable.js +32 -0
  88. package/dist/service/portable.js.map +1 -0
  89. package/dist/service/recovery.d.ts +27 -0
  90. package/dist/service/recovery.js +58 -0
  91. package/dist/service/recovery.js.map +1 -0
  92. package/dist/service/registration.d.ts +82 -0
  93. package/dist/service/registration.js +114 -0
  94. package/dist/service/registration.js.map +1 -0
  95. package/dist/service/systemd-unit.d.ts +7 -0
  96. package/dist/service/systemd-unit.js +43 -0
  97. package/dist/service/systemd-unit.js.map +1 -0
  98. package/dist/service/systemd.d.ts +5 -0
  99. package/dist/service/systemd.js +72 -0
  100. package/dist/service/systemd.js.map +1 -0
  101. package/dist/service/windows-action.d.ts +9 -0
  102. package/dist/service/windows-action.js +55 -0
  103. package/dist/service/windows-action.js.map +1 -0
  104. package/dist/service/windows-task.d.ts +9 -0
  105. package/dist/service/windows-task.js +46 -0
  106. package/dist/service/windows-task.js.map +1 -0
  107. package/dist/service/windows.d.ts +2 -0
  108. package/dist/service/windows.js +65 -0
  109. package/dist/service/windows.js.map +1 -0
  110. package/dist/sqlite.d.ts +4 -0
  111. package/dist/sqlite.js +16 -0
  112. package/dist/sqlite.js.map +1 -0
  113. package/dist/updates/artifacts.d.ts +40 -0
  114. package/dist/updates/artifacts.js +299 -0
  115. package/dist/updates/artifacts.js.map +1 -0
  116. package/dist/updates/bootstrap.d.ts +48 -0
  117. package/dist/updates/bootstrap.js +384 -0
  118. package/dist/updates/bootstrap.js.map +1 -0
  119. package/dist/updates/controller.d.ts +66 -0
  120. package/dist/updates/controller.js +322 -0
  121. package/dist/updates/controller.js.map +1 -0
  122. package/dist/updates/isolated-command-lifetime.d.ts +1 -0
  123. package/dist/updates/isolated-command-lifetime.js +63 -0
  124. package/dist/updates/isolated-command-lifetime.js.map +1 -0
  125. package/dist/updates/store.d.ts +41 -0
  126. package/dist/updates/store.js +80 -0
  127. package/dist/updates/store.js.map +1 -0
  128. package/dist/updates/trust.d.ts +20 -0
  129. package/dist/updates/trust.js +138 -0
  130. package/dist/updates/trust.js.map +1 -0
  131. package/dist/user-ground-host.d.ts +4 -1
  132. package/dist/user-ground-host.js +16 -3
  133. package/dist/user-ground-host.js.map +1 -1
  134. package/dist/watching/host.js +4 -2
  135. package/dist/watching/host.js.map +1 -1
  136. package/dist/workspace-add-staging.js +2 -2
  137. package/dist/workspace-add-staging.js.map +1 -1
  138. package/examinations/fixtures/machine-control-plane.js +57 -0
  139. package/examinations/fixtures/private-wire-authority.js +1065 -0
  140. package/examinations/native-service.mjs +92 -0
  141. package/examinations/network-view.mjs +202 -0
  142. package/examinations/runtime-upgrade.native-test.mjs +198 -0
  143. package/npm-shrinkwrap.json +2097 -218
  144. package/package.json +95 -14
@@ -0,0 +1,28 @@
1
+ import { openFileDatabase } from '../sqlite.js';
2
+ import { dirname } from 'node:path';
3
+ import { ensurePrivateDir } from '../filesystem.js';
4
+ /** An OS-held file lock ends on process exit, survives suspension and cannot
5
+ * be stolen by age or PID reuse. The file itself is never removed. */
6
+ export function acquireProcessLease(file) {
7
+ ensurePrivateDir(dirname(file));
8
+ const database = openFileDatabase(file, { timeout: 0 });
9
+ try {
10
+ database.exec('BEGIN EXCLUSIVE');
11
+ }
12
+ catch (error) {
13
+ database.close();
14
+ if (error.code === 'SQLITE_BUSY')
15
+ return null;
16
+ throw error;
17
+ }
18
+ return { close() { if (database.open)
19
+ database.close(); } };
20
+ }
21
+ export function processLeaseHeld(file) {
22
+ const lease = acquireProcessLease(file);
23
+ if (!lease)
24
+ return true;
25
+ lease.close();
26
+ return false;
27
+ }
28
+ //# sourceMappingURL=lease.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lease.js","sourceRoot":"","sources":["../../src/installation/lease.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD;sEACsE;AACtE,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;IACxD,IAAI,CAAC;QAAC,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAAC,CAAC;IACzC,OAAO,KAAK,EAAE,CAAC;QACb,QAAQ,CAAC,KAAK,EAAE,CAAC;QACjB,IAAK,KAA2B,CAAC,IAAI,KAAK,aAAa;YAAE,OAAO,IAAI,CAAC;QACrE,MAAM,KAAK,CAAC;IACd,CAAC;IACD,OAAO,EAAE,KAAK,KAAK,IAAI,QAAQ,CAAC,IAAI;YAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,KAAK,CAAC,KAAK,EAAE,CAAC;IACd,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { type RuntimeBinding } from '@amalgm/core/identity';
2
+ /** One machine-local ownership ledger, independent of any selected lane.
3
+ * SQLite serializes competing processes; no polling or idle worker is needed.
4
+ * Root claims survive shutdown because stopped runtimes still own their data. */
5
+ export declare class InstallationOwnership {
6
+ private readonly database;
7
+ private readonly runtimeLeases;
8
+ private readonly leaseDirectory;
9
+ readonly installationRoot: string;
10
+ readonly binding: RuntimeBinding;
11
+ constructor(input: {
12
+ home: string;
13
+ installationRoot: string;
14
+ binding: RuntimeBinding;
15
+ });
16
+ /** Reserve before registration, materialization, Watch or another writer.
17
+ * Empty scope reserves the installation container, not a user's workspace. */
18
+ reserve(requestedPath: string, userScope?: string): string;
19
+ /** Serialize initialization with other claimants before creating a manifest. */
20
+ initialize<T>(effect: () => T): T;
21
+ /** An OS-held SQLite write lock is the lease: process exit releases it,
22
+ * suspension does not, and PID reuse cannot either steal or strand it. */
23
+ acquireRuntime(userScope: string): void;
24
+ releaseRuntime(userScope: string): void;
25
+ /** Contention is bounded setup work, never an idle ownership-recovery poll. */
26
+ waitForRuntime(userScope: string, timeoutMs?: number): Promise<void>;
27
+ close(): void;
28
+ }
29
+ /** Resolve existing symlink ancestors even before a new destination exists. */
30
+ export declare function physicalPath(requestedPath: string): string;
@@ -0,0 +1,156 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { existsSync, mkdirSync, realpathSync, statSync } from 'node:fs';
3
+ import { basename, dirname, join, parse, resolve, sep } from 'node:path';
4
+ import { openFileDatabase } from '../sqlite.js';
5
+ import { acquireProcessLease } from './lease.js';
6
+ import { resolveRuntimeBinding, runtimeBindingsMatch, writableRootsOverlap, } from '@amalgm/core/identity';
7
+ /** One machine-local ownership ledger, independent of any selected lane.
8
+ * SQLite serializes competing processes; no polling or idle worker is needed.
9
+ * Root claims survive shutdown because stopped runtimes still own their data. */
10
+ export class InstallationOwnership {
11
+ database;
12
+ runtimeLeases = new Map();
13
+ leaseDirectory;
14
+ installationRoot;
15
+ binding;
16
+ constructor(input) {
17
+ this.binding = resolveRuntimeBinding(input.binding);
18
+ this.installationRoot = physicalPath(input.installationRoot);
19
+ const directory = join(input.home, '.amalgm');
20
+ this.leaseDirectory = join(directory, 'owners');
21
+ mkdirSync(directory, { recursive: true, mode: 0o700 });
22
+ this.database = openFileDatabase(join(directory, 'installation-ownership.sqlite'));
23
+ this.database.pragma('busy_timeout = 5000');
24
+ this.database.exec(`
25
+ CREATE TABLE IF NOT EXISTS writable_roots (
26
+ path TEXT PRIMARY KEY, installation TEXT NOT NULL, binding TEXT NOT NULL,
27
+ user_scope TEXT NOT NULL, physical TEXT NOT NULL
28
+ );
29
+ `);
30
+ try {
31
+ this.reserve(this.installationRoot);
32
+ }
33
+ catch (error) {
34
+ this.database.close();
35
+ throw error;
36
+ }
37
+ }
38
+ /** Reserve before registration, materialization, Watch or another writer.
39
+ * Empty scope reserves the installation container, not a user's workspace. */
40
+ reserve(requestedPath, userScope = '') {
41
+ const path = physicalPath(requestedPath);
42
+ const physical = physicalComponents(path);
43
+ const binding = JSON.stringify(this.binding);
44
+ this.database.transaction(() => {
45
+ const claims = this.database.prepare('SELECT * FROM writable_roots').all();
46
+ for (const claim of claims) {
47
+ const previous = physicalComponents(claim.path);
48
+ const recorded = JSON.parse(claim.physical);
49
+ const overlaps = writableRootsOverlap(pathComponents(path), pathComponents(claim.path))
50
+ || writableRootsOverlap(physical, previous)
51
+ || writableRootsOverlap(physical, recorded)
52
+ || (recorded.at(-1).startsWith('inode:') && physical.includes(recorded.at(-1)))
53
+ || (physical.at(-1).startsWith('inode:') && recorded.includes(physical.at(-1)));
54
+ if (!overlaps)
55
+ continue;
56
+ const sameInstallation = claim.installation === this.installationRoot
57
+ && runtimeBindingsMatch(JSON.parse(claim.binding), this.binding);
58
+ const sameUser = !claim.user_scope || !userScope || claim.user_scope === userScope;
59
+ if (!sameInstallation || !sameUser) {
60
+ throw Object.assign(new Error(`Writable root ${path} overlaps ${claim.path}, owned by another Amalgm installation or user. Use a separate checkout.`), {
61
+ code: 'installation_root_conflict',
62
+ });
63
+ }
64
+ }
65
+ const existing = this.database.prepare('SELECT * FROM writable_roots WHERE path = ?').get(path);
66
+ if (!existing) {
67
+ this.database.prepare('INSERT INTO writable_roots VALUES (?, ?, ?, ?, ?)')
68
+ .run(path, this.installationRoot, binding, userScope, JSON.stringify(physical));
69
+ }
70
+ }).immediate();
71
+ return path;
72
+ }
73
+ /** Serialize initialization with other claimants before creating a manifest. */
74
+ initialize(effect) {
75
+ return this.database.transaction(effect).immediate();
76
+ }
77
+ /** An OS-held SQLite write lock is the lease: process exit releases it,
78
+ * suspension does not, and PID reuse cannot either steal or strand it. */
79
+ acquireRuntime(userScope) {
80
+ if (!userScope)
81
+ throw new Error('Runtime ownership requires a user scope.');
82
+ if (this.runtimeLeases.has(userScope))
83
+ return;
84
+ const scope = createHash('sha256').update(JSON.stringify([this.binding, userScope])).digest('hex');
85
+ const lease = acquireProcessLease(join(this.leaseDirectory, `${scope}.sqlite`));
86
+ if (!lease)
87
+ throw Object.assign(new Error(`Amalgm already has a runtime owner for ${userScope} in this environment. Bind to that runtime.`), {
88
+ code: 'runtime_already_owned',
89
+ });
90
+ this.runtimeLeases.set(userScope, lease);
91
+ }
92
+ releaseRuntime(userScope) {
93
+ const lease = this.runtimeLeases.get(userScope);
94
+ if (!lease)
95
+ return;
96
+ lease.close();
97
+ this.runtimeLeases.delete(userScope);
98
+ }
99
+ /** Contention is bounded setup work, never an idle ownership-recovery poll. */
100
+ async waitForRuntime(userScope, timeoutMs = 600_000) {
101
+ const deadline = Date.now() + timeoutMs;
102
+ for (;;) {
103
+ try {
104
+ this.acquireRuntime(userScope);
105
+ return;
106
+ }
107
+ catch (error) {
108
+ if (error.code !== 'runtime_already_owned' || Date.now() >= deadline)
109
+ throw error;
110
+ }
111
+ await new Promise((done) => setTimeout(done, 250));
112
+ }
113
+ }
114
+ close() {
115
+ for (const scope of this.runtimeLeases.keys())
116
+ this.releaseRuntime(scope);
117
+ if (this.database.open)
118
+ this.database.close();
119
+ }
120
+ }
121
+ /** Resolve existing symlink ancestors even before a new destination exists. */
122
+ export function physicalPath(requestedPath) {
123
+ let ancestor = resolve(requestedPath);
124
+ const absent = [];
125
+ while (!existsSync(ancestor)) {
126
+ const parent = dirname(ancestor);
127
+ if (parent === ancestor)
128
+ throw new Error(`Cannot resolve physical root ${requestedPath}`);
129
+ absent.unshift(basename(ancestor));
130
+ ancestor = parent;
131
+ }
132
+ return join(realpathSync.native(ancestor), ...absent);
133
+ }
134
+ function physicalComponents(path) {
135
+ const root = parse(path).root;
136
+ const components = [root, ...path.slice(root.length).split(sep).filter(Boolean)];
137
+ let current = root;
138
+ return components.map((component, index) => {
139
+ if (index > 0)
140
+ current = join(current, component);
141
+ try {
142
+ const info = statSync(current);
143
+ return `inode:${info.dev}:${info.ino}:${info.birthtimeMs}`;
144
+ }
145
+ catch (error) {
146
+ if (error.code !== 'ENOENT')
147
+ throw error;
148
+ return `name:${process.platform === 'win32' ? component.toLowerCase() : component}`;
149
+ }
150
+ });
151
+ }
152
+ function pathComponents(path) {
153
+ const absolute = process.platform === 'win32' ? path.toLowerCase() : path;
154
+ return [parse(absolute).root, ...absolute.slice(parse(absolute).root.length).split(sep).filter(Boolean)];
155
+ }
156
+ //# sourceMappingURL=ownership.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ownership.js","sourceRoot":"","sources":["../../src/installation/ownership.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { type RuntimeBinding, type RuntimeLabel } from '@amalgm/core/identity';
2
+ import type { ParsedArguments } from '../cli-arguments.js';
3
+ /** Public command prefixes select the environment, never ambient env vars. */
4
+ export declare function selectRuntimeInvocation(args: readonly string[]): {
5
+ runtimeLabel: RuntimeLabel;
6
+ args: readonly string[];
7
+ };
8
+ export declare function resolveInvocationBinding(runtimeLabel: RuntimeLabel, parsed: ParsedArguments): RuntimeBinding;
@@ -0,0 +1,29 @@
1
+ import { resolveRuntimeBinding } from '@amalgm/core/identity';
2
+ /** Public command prefixes select the environment, never ambient env vars. */
3
+ export function selectRuntimeInvocation(args) {
4
+ if (args[0] === 'preview')
5
+ return { runtimeLabel: 'preview', args: args.slice(1) };
6
+ if (args[0] === 'dev')
7
+ return { runtimeLabel: 'local', args: args.slice(1) };
8
+ return { runtimeLabel: 'main', args };
9
+ }
10
+ export function resolveInvocationBinding(runtimeLabel, parsed) {
11
+ const explicitLabel = stringOption(parsed, 'runtime-label');
12
+ if (explicitLabel !== undefined && explicitLabel !== runtimeLabel) {
13
+ throw new Error('The runtime label conflicts with the command prefix. Use amalgm preview … or amalgm dev … to select that environment.');
14
+ }
15
+ return resolveRuntimeBinding({
16
+ runtimeLabel,
17
+ branch: stringOption(parsed, 'branch'),
18
+ localSession: stringOption(parsed, 'local-session'),
19
+ });
20
+ }
21
+ function stringOption(parsed, name) {
22
+ const value = parsed.options[name];
23
+ if (value === undefined)
24
+ return undefined;
25
+ if (typeof value !== 'string' || value.length === 0)
26
+ throw new Error(`--${name} requires a value.`);
27
+ return value;
28
+ }
29
+ //# sourceMappingURL=selection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection.js","sourceRoot":"","sources":["../../src/installation/selection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAA0C,MAAM,uBAAuB,CAAC;AAGtG,8EAA8E;AAC9E,MAAM,UAAU,uBAAuB,CAAC,IAAuB;IAC7D,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS;QAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACnF,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK;QAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,YAA0B,EAAE,MAAuB;IAC1F,MAAM,aAAa,GAAG,YAAY,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC5D,IAAI,aAAa,KAAK,SAAS,IAAI,aAAa,KAAK,YAAY,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CAAC,uHAAuH,CAAC,CAAC;IAC3I,CAAC;IACD,OAAO,qBAAqB,CAAC;QAC3B,YAAY;QACZ,MAAM,EAAE,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC;QACtC,YAAY,EAAE,YAAY,CAAC,MAAM,EAAE,eAAe,CAAC;KACpD,CAAC,CAAC;AACL,CAAC;AAED,SAAS,YAAY,CAAC,MAAuB,EAAE,IAAY;IACzD,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,KAAK,IAAI,oBAAoB,CAAC,CAAC;IACpG,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -1,14 +1,14 @@
1
1
  import type { ChannelsCommands } from "@amalgm/channels";
2
2
  import type { ChatRuntimePort } from "@amalgm/chat";
3
- import { type JoinMachineInput, type MachineSetupPorts, type ReadyMachine } from "@amalgm/core/identity";
4
- import { type FilesAddResult } from "@amalgm/live/files";
3
+ import { type JoinMachineInput, type MachineSetupPorts, type ReadyMachine, type RuntimeBinding } from "@amalgm/core/identity";
4
+ import type { FilesAddResult } from "@amalgm/live/files";
5
5
  import { type FilesStageObserver } from "./files-observability.js";
6
6
  import type { EntityApplyStageEvidence } from "./entity-apply-host.js";
7
7
  import { type DeviceKeyStore } from "./authorization/index.js";
8
8
  import { type AuthorizationKeyRecoveryResult } from "./authorization/recovery-host.js";
9
- import { type PlatformProductHostOptions } from "./platform-product-host.js";
9
+ import type { PlatformProductHostOptions } from "./platform-product-host.js";
10
10
  import { type RuntimeCommandConnection } from "./runtime-command-host.js";
11
- import { UserGroundHost, type DetectScanEvidence, type UserGroundCloseOptions, type WorkspaceAddStage } from "./user-ground-host.js";
11
+ import type { UserGroundHost, DetectScanEvidence, UserGroundCloseOptions, WorkspaceAddStage } from "./user-ground-host.js";
12
12
  import type { OpenNativeWatch, WatchCoverageEvidence, WatchHealth } from "./watching/index.js";
13
13
  export interface MachineHostOptions {
14
14
  readonly homedir?: string;
@@ -19,7 +19,11 @@ export interface MachineHostOptions {
19
19
  readonly runtimeVersion: string;
20
20
  readonly runtimeLabel?: string;
21
21
  readonly branch?: string;
22
+ readonly localSession?: string;
23
+ /** Explicit local availability; managed installations retain their release selection. */
24
+ readonly services?: readonly string[];
22
25
  readonly proxyUrl?: string;
26
+ readonly wireUrl?: string;
23
27
  /** Hosted product endpoints. Omit in isolated hosts that do not compose them. */
24
28
  readonly platformProducts?: Omit<PlatformProductHostOptions, 'authorization'>;
25
29
  /** Test/adapter seam; production defaults to the OS-backed device key store. */
@@ -63,6 +67,7 @@ interface MachinePaths {
63
67
  readonly status: string;
64
68
  }
65
69
  export interface MachineStatus {
70
+ readonly binding: RuntimeBinding;
66
71
  readonly user: string;
67
72
  readonly deviceId: string | null;
68
73
  readonly registration: "absent" | "incomplete" | "ready";
@@ -74,6 +79,14 @@ export interface MachineStatus {
74
79
  readonly machineDir: string | null;
75
80
  readonly database: string | null;
76
81
  }
82
+ type HostJoinInput = Omit<JoinMachineInput, 'appUrl' | 'platform' | 'appVersion' | 'runtimeLabel' | 'branch' | 'localSession'>;
83
+ export interface MachineSetupResult {
84
+ readonly disposition: 'enrolled' | 'adopted';
85
+ readonly userEmail: string;
86
+ readonly userId: string;
87
+ readonly computerId: string;
88
+ readonly deviceId: string;
89
+ }
77
90
  /** The production effects around Core's machine-setup operation. It does not
78
91
  * decide ordering, readiness, or installation selection; those remain Core. */
79
92
  export declare class MachineHost {
@@ -82,13 +95,19 @@ export declare class MachineHost {
82
95
  readonly amalgmRoot: string;
83
96
  readonly deviceFile: string;
84
97
  readonly ports: MachineSetupPorts;
98
+ readonly binding: RuntimeBinding;
99
+ private readonly ownership;
85
100
  private selectedUserEmail;
86
101
  private groundHost;
87
102
  private running;
88
103
  private readonly stages;
89
104
  constructor(options: MachineHostOptions);
90
- join(input: Omit<JoinMachineInput, "appUrl" | "platform" | "appVersion" | "runtimeLabel" | "branch">): Promise<ReadyMachine>;
105
+ private approveSetup;
106
+ join(input: HostJoinInput): Promise<ReadyMachine>;
107
+ /** Shared, finite UI setup. An existing owner is never disturbed by adoption. */
108
+ setup(input: HostJoinInput): Promise<MachineSetupResult>;
91
109
  resume(): Promise<ReadyMachine>;
110
+ assertRuntimeCanStart(): void;
92
111
  recoverAuthorizationKey(input?: Readonly<{
93
112
  setupCode?: string;
94
113
  }>): Promise<AuthorizationKeyRecoveryResult>;
@@ -116,6 +135,7 @@ export declare class MachineHost {
116
135
  * loopback MCP route. Shell alone reads the local admission capability. */
117
136
  channelsCommands(): ChannelsCommands;
118
137
  close(options?: UserGroundCloseOptions): Promise<void>;
138
+ private drainRuntime;
119
139
  private ensureInstallationRoot;
120
140
  private openChannelsCommands;
121
141
  private runtimeCommandAddress;
@@ -124,8 +144,10 @@ export declare class MachineHost {
124
144
  private paths;
125
145
  private requireSelectedUser;
126
146
  private resolveUserForResume;
147
+ private assertRecordBinding;
127
148
  private loadMachine;
128
149
  private saveMachine;
150
+ private acquireRuntimeOwnership;
129
151
  private startRuntime;
130
152
  }
131
153
  export declare function defaultMachineName(): string;