@sentropic/llm-mesh 0.32.3 → 0.33.0
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.
- package/dist/enrollment/index.d.ts +4 -0
- package/dist/enrollment/index.d.ts.map +1 -1
- package/dist/enrollment/index.js +2 -0
- package/dist/enrollment/index.js.map +1 -1
- package/dist/enrollment/seat-onboarding-projections.d.ts +44 -0
- package/dist/enrollment/seat-onboarding-projections.d.ts.map +1 -0
- package/dist/enrollment/seat-onboarding-projections.js +113 -0
- package/dist/enrollment/seat-onboarding-projections.js.map +1 -0
- package/dist/enrollment/seat-onboarding.d.ts +161 -0
- package/dist/enrollment/seat-onboarding.d.ts.map +1 -0
- package/dist/enrollment/seat-onboarding.js +698 -0
- package/dist/enrollment/seat-onboarding.js.map +1 -0
- package/dist/node/index.d.ts +9 -1
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +5 -1
- package/dist/node/index.js.map +1 -1
- package/dist/node/keyring/encrypted-file-keyring.d.ts +6 -0
- package/dist/node/keyring/encrypted-file-keyring.d.ts.map +1 -1
- package/dist/node/keyring/encrypted-file-keyring.js +51 -9
- package/dist/node/keyring/encrypted-file-keyring.js.map +1 -1
- package/dist/node/seat-onboarding-capture.d.ts +47 -0
- package/dist/node/seat-onboarding-capture.d.ts.map +1 -0
- package/dist/node/seat-onboarding-capture.js +164 -0
- package/dist/node/seat-onboarding-capture.js.map +1 -0
- package/dist/node/seat-onboarding-cell-compose.d.ts +25 -0
- package/dist/node/seat-onboarding-cell-compose.d.ts.map +1 -0
- package/dist/node/seat-onboarding-cell-compose.js +117 -0
- package/dist/node/seat-onboarding-cell-compose.js.map +1 -0
- package/dist/node/seat-onboarding-erase.d.ts +8 -0
- package/dist/node/seat-onboarding-erase.d.ts.map +1 -0
- package/dist/node/seat-onboarding-erase.js +31 -0
- package/dist/node/seat-onboarding-erase.js.map +1 -0
- package/dist/node/seat-onboarding-materialize.d.ts +6 -0
- package/dist/node/seat-onboarding-materialize.d.ts.map +1 -0
- package/dist/node/seat-onboarding-materialize.js +11 -0
- package/dist/node/seat-onboarding-materialize.js.map +1 -0
- package/dist/node/seat-onboarding-record.d.ts +11 -0
- package/dist/node/seat-onboarding-record.d.ts.map +1 -0
- package/dist/node/seat-onboarding-record.js +86 -0
- package/dist/node/seat-onboarding-record.js.map +1 -0
- package/dist/node/seat-onboarding-stage1.d.ts +11 -0
- package/dist/node/seat-onboarding-stage1.d.ts.map +1 -0
- package/dist/node/seat-onboarding-stage1.js +121 -0
- package/dist/node/seat-onboarding-stage1.js.map +1 -0
- package/dist/node/seat-onboarding-stage2.d.ts +10 -0
- package/dist/node/seat-onboarding-stage2.d.ts.map +1 -0
- package/dist/node/seat-onboarding-stage2.js +110 -0
- package/dist/node/seat-onboarding-stage2.js.map +1 -0
- package/dist/node/seat-onboarding-types.d.ts +106 -0
- package/dist/node/seat-onboarding-types.d.ts.map +1 -0
- package/dist/node/seat-onboarding-types.js +6 -0
- package/dist/node/seat-onboarding-types.js.map +1 -0
- package/dist/node/seat-stage-write.d.ts +25 -0
- package/dist/node/seat-stage-write.d.ts.map +1 -0
- package/dist/node/seat-stage-write.js +93 -0
- package/dist/node/seat-stage-write.js.map +1 -0
- package/dist/service/facade.d.ts +10 -0
- package/dist/service/facade.d.ts.map +1 -1
- package/dist/service/facade.js +3 -0
- package/dist/service/facade.js.map +1 -1
- package/dist/service/local-account-transport-service.d.ts +39 -0
- package/dist/service/local-account-transport-service.d.ts.map +1 -1
- package/dist/service/local-account-transport-service.js +158 -0
- package/dist/service/local-account-transport-service.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Stage-2 cell-side composition: map seat-storage auth names to cell
|
|
3
|
+
// destinations (§3.2), compose the claude `.claude.json` as its single
|
|
4
|
+
// writer, and resolve receipt paths. Internal module: not exported from the
|
|
5
|
+
// package entry points.
|
|
6
|
+
import { lstat, readFile } from 'node:fs/promises';
|
|
7
|
+
import { join, relative, resolve } from 'node:path';
|
|
8
|
+
import { renderCodexSeatConfig } from '../enrollment/seat-onboarding-projections.js';
|
|
9
|
+
import { decodeBase64, fail, isRecord, sha256Hex, utf8, withinRoot, } from './seat-stage-write.js';
|
|
10
|
+
/** Map a seat-storage auth name to its cell destination (§3.2). */
|
|
11
|
+
export function authCellDest(name, cellHome, configDirs) {
|
|
12
|
+
if (name.startsWith('.claude/'))
|
|
13
|
+
return join(configDirs.claudeConfigDir, name.slice('.claude/'.length));
|
|
14
|
+
if (name === '.claude.json')
|
|
15
|
+
return join(configDirs.claudeConfigDir, '.claude.json');
|
|
16
|
+
if (name.startsWith('.codex/'))
|
|
17
|
+
return join(configDirs.codexHome, name.slice('.codex/'.length));
|
|
18
|
+
if (name.startsWith('.config/'))
|
|
19
|
+
return join(configDirs.xdgConfigHome, name.slice('.config/'.length));
|
|
20
|
+
return join(cellHome, name);
|
|
21
|
+
}
|
|
22
|
+
/** Receipt path relative to the owning cell root (names only, §3.6). */
|
|
23
|
+
export function receiptRelPath(path, cellHome, configDirs) {
|
|
24
|
+
if (withinRoot(cellHome, path))
|
|
25
|
+
return relative(resolve(cellHome), resolve(path));
|
|
26
|
+
for (const dir of Object.values(configDirs)) {
|
|
27
|
+
if (withinRoot(dir, path))
|
|
28
|
+
return relative(resolve(dir), resolve(path));
|
|
29
|
+
}
|
|
30
|
+
return resolve(path);
|
|
31
|
+
}
|
|
32
|
+
const CLAUDE_SINGLE_WRITER_KEYS = ['projects', 'hasCompletedOnboarding', 'oauthAccount'];
|
|
33
|
+
/** Compose the cell `.claude.json`: auth projection + onboarding projection + trust synthesis + MCP config merged last. */
|
|
34
|
+
export function composeClaudeJson(authBytes, onboardingBytes, workspaceDir, cellSynthesis, claudeMcpConfig) {
|
|
35
|
+
let authObj;
|
|
36
|
+
let onboardObj;
|
|
37
|
+
try {
|
|
38
|
+
authObj = JSON.parse(new TextDecoder().decode(authBytes));
|
|
39
|
+
onboardObj = JSON.parse(new TextDecoder().decode(onboardingBytes));
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
fail('onboarding-shape-unverified', 'claude projection content is not JSON');
|
|
43
|
+
}
|
|
44
|
+
if (!isRecord(authObj) || !isRecord(onboardObj))
|
|
45
|
+
fail('onboarding-shape-unverified', 'claude projections must be objects');
|
|
46
|
+
if (authObj['hasCompletedOnboarding'] !== undefined &&
|
|
47
|
+
onboardObj['hasCompletedOnboarding'] !== undefined &&
|
|
48
|
+
authObj['hasCompletedOnboarding'] !== onboardObj['hasCompletedOnboarding']) {
|
|
49
|
+
fail('onboarding-shape-unverified', 'auth and onboarding projections conflict on hasCompletedOnboarding');
|
|
50
|
+
}
|
|
51
|
+
const composed = {};
|
|
52
|
+
if (authObj['oauthAccount'] !== undefined)
|
|
53
|
+
composed['oauthAccount'] = authObj['oauthAccount'];
|
|
54
|
+
const completed = onboardObj['hasCompletedOnboarding'] ?? authObj['hasCompletedOnboarding'];
|
|
55
|
+
if (completed !== undefined)
|
|
56
|
+
composed['hasCompletedOnboarding'] = completed;
|
|
57
|
+
const lastVersion = onboardObj['lastOnboardingVersion'] ?? authObj['lastOnboardingVersion'];
|
|
58
|
+
if (lastVersion !== undefined)
|
|
59
|
+
composed['lastOnboardingVersion'] = lastVersion;
|
|
60
|
+
if (cellSynthesis.includes('claude-workspace-trust')) {
|
|
61
|
+
composed['projects'] = { [workspaceDir]: { hasTrustDialogAccepted: true } };
|
|
62
|
+
}
|
|
63
|
+
for (const [key, value] of Object.entries(claudeMcpConfig ?? {})) {
|
|
64
|
+
if (CLAUDE_SINGLE_WRITER_KEYS.includes(key)) {
|
|
65
|
+
fail('onboarding-shape-unverified', `claudeMcpConfig key has a single writer: ${key}`);
|
|
66
|
+
}
|
|
67
|
+
composed[key] = value;
|
|
68
|
+
}
|
|
69
|
+
return `${JSON.stringify(composed, null, 2)}\n`;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Plan the onboarding writes for one cell: the canonical agy bytes, the
|
|
73
|
+
* composed claude `.claude.json`, the synthesized muse trust file, or the
|
|
74
|
+
* rendered codex `config.toml` — exactly one file per CLI, digest-checked.
|
|
75
|
+
*/
|
|
76
|
+
export async function planOnboardingWrites(input) {
|
|
77
|
+
const { cli, onboarding, seatDir, cellHome, workspaceDir, configDirs } = input;
|
|
78
|
+
const file = onboarding.files[0];
|
|
79
|
+
const bytes = decodeBase64(file.contentBase64);
|
|
80
|
+
if (sha256Hex(bytes) !== file.sha256 || bytes.length !== file.byteLength) {
|
|
81
|
+
fail('onboarding-shape-unverified', 'onboarding file digest mismatch');
|
|
82
|
+
}
|
|
83
|
+
if (cli === 'agy') {
|
|
84
|
+
return [{ path: join(cellHome, '.gemini/antigravity-cli/jetski_state.pbtxt'), bytes, cls: 'onboarding' }];
|
|
85
|
+
}
|
|
86
|
+
if (cli === 'claude') {
|
|
87
|
+
const authPath = join(seatDir, '.claude.json');
|
|
88
|
+
const authSt = await lstat(authPath).catch(() => null);
|
|
89
|
+
if (!authSt || !authSt.isFile() || authSt.isSymbolicLink()) {
|
|
90
|
+
fail('onboarding-shape-unverified', 'claude auth .claude.json missing in seatDir');
|
|
91
|
+
}
|
|
92
|
+
const composed = composeClaudeJson(new Uint8Array(await readFile(authPath)), bytes, workspaceDir, onboarding.cellSynthesis, input.claudeMcpConfig);
|
|
93
|
+
return [{ path: join(configDirs.claudeConfigDir, '.claude.json'), bytes: utf8(composed), cls: 'composed' }];
|
|
94
|
+
}
|
|
95
|
+
if (cli === 'muse') {
|
|
96
|
+
if (!onboarding.cellSynthesis.includes('muse-workspace-trust'))
|
|
97
|
+
return [];
|
|
98
|
+
let proj;
|
|
99
|
+
try {
|
|
100
|
+
proj = JSON.parse(new TextDecoder().decode(bytes));
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
fail('onboarding-shape-unverified', 'muse trust content is not JSON');
|
|
104
|
+
}
|
|
105
|
+
if (!isRecord(proj))
|
|
106
|
+
fail('onboarding-shape-unverified', 'muse trust must be an object');
|
|
107
|
+
const content = `${JSON.stringify({ schema_version: proj['schema_version'], projects: { [workspaceDir]: { decision: 'trusted' } } }, null, 2)}\n`;
|
|
108
|
+
return [{ path: join(configDirs.xdgConfigHome, 'muse/trust.json'), bytes: utf8(content), cls: 'synthesized' }];
|
|
109
|
+
}
|
|
110
|
+
// codex
|
|
111
|
+
const toml = renderCodexSeatConfig(new TextDecoder().decode(bytes), workspaceDir, {
|
|
112
|
+
projectTrust: onboarding.cellSynthesis.includes('codex-project-trust'),
|
|
113
|
+
mcpServers: input.codexMcpServers,
|
|
114
|
+
});
|
|
115
|
+
return [{ path: join(configDirs.codexHome, 'config.toml'), bytes: utf8(toml), cls: 'synthesized' }];
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=seat-onboarding-cell-compose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seat-onboarding-cell-compose.js","sourceRoot":"","sources":["../../src/node/seat-onboarding-cell-compose.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SeatEraseResult } from './seat-onboarding-types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Whole-root erasure of a stage-1 seat directory or a stage-2 cell HOME.
|
|
4
|
+
* Returns the surviving-path list (empty = proven); never follows a
|
|
5
|
+
* symlinked root.
|
|
6
|
+
*/
|
|
7
|
+
export declare function eraseSeatHome(rootDir: string): Promise<SeatEraseResult>;
|
|
8
|
+
//# sourceMappingURL=seat-onboarding-erase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seat-onboarding-erase.d.ts","sourceRoot":"","sources":["../../src/node/seat-onboarding-erase.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAKlE;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAa7E"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Erasure: whole-root wipe of a stage-1 seat directory or a stage-2 cell
|
|
3
|
+
// HOME, returning the surviving-path list (empty = proven).
|
|
4
|
+
import { lstat, rm } from 'node:fs/promises';
|
|
5
|
+
import { resolve, sep } from 'node:path';
|
|
6
|
+
import { asResult, fail } from './seat-stage-write.js';
|
|
7
|
+
// ── erasure ──────────────────────────────────────────────────────────────
|
|
8
|
+
/**
|
|
9
|
+
* Whole-root erasure of a stage-1 seat directory or a stage-2 cell HOME.
|
|
10
|
+
* Returns the surviving-path list (empty = proven); never follows a
|
|
11
|
+
* symlinked root.
|
|
12
|
+
*/
|
|
13
|
+
export async function eraseSeatHome(rootDir) {
|
|
14
|
+
try {
|
|
15
|
+
if (typeof rootDir !== 'string' || rootDir.length === 0)
|
|
16
|
+
fail('onboarding-schema-mismatch', 'rootDir is required');
|
|
17
|
+
const resolved = resolve(rootDir);
|
|
18
|
+
if (resolved === sep)
|
|
19
|
+
fail('onboarding-shape-unverified', 'refusing to erase the filesystem root');
|
|
20
|
+
const st = await lstat(resolved).catch(() => null);
|
|
21
|
+
if (st && st.isSymbolicLink())
|
|
22
|
+
fail('onboarding-shape-unverified', 'refusing to erase through a symlink');
|
|
23
|
+
await rm(resolved, { recursive: true, force: true });
|
|
24
|
+
const after = await lstat(resolved).catch(() => null);
|
|
25
|
+
return { ok: true, survivingPaths: after ? [resolved] : [] };
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
return asResult(error);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=seat-onboarding-erase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seat-onboarding-erase.js","sourceRoot":"","sources":["../../src/node/seat-onboarding-erase.ts"],"names":[],"mappings":"AAAA,EAAE;AACF,yEAAyE;AACzE,4DAA4D;AAE5D,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAGzC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAEvD,4EAA4E;AAE5E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAe;IACjD,IAAI,CAAC;QACH,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,IAAI,CAAC,4BAA4B,EAAE,qBAAqB,CAAC,CAAC;QACnH,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,QAAQ,KAAK,GAAG;YAAE,IAAI,CAAC,6BAA6B,EAAE,uCAAuC,CAAC,CAAC;QACnG,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QACnD,IAAI,EAAE,IAAI,EAAE,CAAC,cAAc,EAAE;YAAE,IAAI,CAAC,6BAA6B,EAAE,qCAAqC,CAAC,CAAC;QAC1G,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QACtD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAC/D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { SEAT_RECORD_REL_PATH } from './seat-stage-write.js';
|
|
2
|
+
export type { PlannedWrite, SeatCellConfigDirs, SeatCellInput, SeatCellReceipt, SeatCellReceiptFile, SeatCellResult, SeatCodexMcpServer, SeatEraseResult, SeatRecordView, SeatStageInput, SeatStageInputSeat, SeatStageReceipt, SeatStageReceiptEntry, SeatStageReceiptOnboarding, SeatStageResult, } from './seat-onboarding-types.js';
|
|
3
|
+
export { materialiseSeatEnvelopes } from './seat-onboarding-stage1.js';
|
|
4
|
+
export { eraseSeatHome } from './seat-onboarding-erase.js';
|
|
5
|
+
export { materialiseCellHome } from './seat-onboarding-stage2.js';
|
|
6
|
+
//# sourceMappingURL=seat-onboarding-materialize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seat-onboarding-materialize.d.ts","sourceRoot":"","sources":["../../src/node/seat-onboarding-materialize.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,EACrB,0BAA0B,EAC1B,eAAe,GAChB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Two-stage seat materialization and erasure (public barrel). Stage 1
|
|
3
|
+
// stages validated envelopes into per-seat directories; stage 2 seeds one
|
|
4
|
+
// fresh cell HOME from a staged seat record; erasure wipes either root.
|
|
5
|
+
// Implementations live in the sibling modules and import only Node builtins
|
|
6
|
+
// plus the enrollment modules, keeping the bench vendor set dependency-closed.
|
|
7
|
+
export { SEAT_RECORD_REL_PATH } from './seat-stage-write.js';
|
|
8
|
+
export { materialiseSeatEnvelopes } from './seat-onboarding-stage1.js';
|
|
9
|
+
export { eraseSeatHome } from './seat-onboarding-erase.js';
|
|
10
|
+
export { materialiseCellHome } from './seat-onboarding-stage2.js';
|
|
11
|
+
//# sourceMappingURL=seat-onboarding-materialize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seat-onboarding-materialize.js","sourceRoot":"","sources":["../../src/node/seat-onboarding-materialize.ts"],"names":[],"mappings":"AAAA,EAAE;AACF,sEAAsE;AACtE,0EAA0E;AAC1E,wEAAwE;AACxE,4EAA4E;AAC5E,+EAA+E;AAE/E,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAkB7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SeatRecordView } from './seat-onboarding-types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Read and re-validate the seat record of a staged seat directory. Throws a
|
|
4
|
+
* StageRefusal (via `fail`) on any mismatch, missing or symlinked record.
|
|
5
|
+
*/
|
|
6
|
+
export declare function readSeatRecord(input: {
|
|
7
|
+
seatDir: string;
|
|
8
|
+
expectedNativeCliVersion: string;
|
|
9
|
+
ownerScope: string;
|
|
10
|
+
}): Promise<SeatRecordView>;
|
|
11
|
+
//# sourceMappingURL=seat-onboarding-record.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seat-onboarding-record.d.ts","sourceRoot":"","sources":["../../src/node/seat-onboarding-record.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAGjE;;;GAGG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,wBAAwB,EAAE,MAAM,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,cAAc,CAAC,CAkE1B"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Stage-2 seat-record read: re-read and re-validate the stage-1 seat record
|
|
3
|
+
// (bundle + onboarding + binding + versions) and re-derive the launch gate.
|
|
4
|
+
// A stored gate that disagrees with the derivation is a tampered record.
|
|
5
|
+
// Internal module: not exported from the package entry points.
|
|
6
|
+
import { lstat, readFile } from 'node:fs/promises';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
import { validateSeatBundle } from '../enrollment/seat-bundle.js';
|
|
9
|
+
import { seatLaunchGate, validateSeatOnboarding, } from '../enrollment/seat-onboarding.js';
|
|
10
|
+
import { SEAT_RECORD_REL_PATH, fail, isRecord } from './seat-stage-write.js';
|
|
11
|
+
/**
|
|
12
|
+
* Read and re-validate the seat record of a staged seat directory. Throws a
|
|
13
|
+
* StageRefusal (via `fail`) on any mismatch, missing or symlinked record.
|
|
14
|
+
*/
|
|
15
|
+
export async function readSeatRecord(input) {
|
|
16
|
+
const { seatDir } = input;
|
|
17
|
+
const seatSt = await lstat(seatDir).catch(() => null);
|
|
18
|
+
if (!seatSt || seatSt.isSymbolicLink() || !seatSt.isDirectory()) {
|
|
19
|
+
fail('onboarding-shape-unverified', 'seatDir must be an existing directory');
|
|
20
|
+
}
|
|
21
|
+
const recordPath = join(seatDir, SEAT_RECORD_REL_PATH);
|
|
22
|
+
const recordSt = await lstat(recordPath).catch(() => null);
|
|
23
|
+
if (!recordSt || recordSt.isSymbolicLink() || !recordSt.isFile()) {
|
|
24
|
+
fail('onboarding-shape-unverified', 'seat record missing or not a regular file');
|
|
25
|
+
}
|
|
26
|
+
let record;
|
|
27
|
+
try {
|
|
28
|
+
record = JSON.parse(await readFile(recordPath, 'utf8'));
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
fail('onboarding-shape-unverified', 'seat record is not JSON');
|
|
32
|
+
}
|
|
33
|
+
if (!isRecord(record))
|
|
34
|
+
fail('onboarding-shape-unverified', 'seat record must be an object');
|
|
35
|
+
const badRecordKey = Object.keys(record).find((k) => !['version', 'bundle', 'onboarding', 'launchGate', 'authFiles'].includes(k));
|
|
36
|
+
if (badRecordKey)
|
|
37
|
+
fail('onboarding-unknown-field', `unknown seat record field: ${badRecordKey}`);
|
|
38
|
+
if (record['version'] !== 1)
|
|
39
|
+
fail('onboarding-schema-mismatch', 'seat record version must be 1');
|
|
40
|
+
const bundleResult = validateSeatBundle(record['bundle'], { trustedAuthority: 'consumer' });
|
|
41
|
+
if (!bundleResult.ok)
|
|
42
|
+
fail(bundleResult.code, bundleResult.detail);
|
|
43
|
+
const bundle = bundleResult.bundle;
|
|
44
|
+
const cli = bundle.identity.cli;
|
|
45
|
+
let onboarding = null;
|
|
46
|
+
let onboardingStatus = 'absent';
|
|
47
|
+
if (record['onboarding'] !== null && record['onboarding'] !== undefined) {
|
|
48
|
+
const blockResult = validateSeatOnboarding(record['onboarding']);
|
|
49
|
+
if (!blockResult.ok)
|
|
50
|
+
fail(blockResult.code, blockResult.detail);
|
|
51
|
+
onboarding = blockResult.block;
|
|
52
|
+
onboardingStatus = 'present';
|
|
53
|
+
const lifecycle = bundle.lifecycle;
|
|
54
|
+
if (onboarding.cli !== cli ||
|
|
55
|
+
onboarding.seatRef !== bundle.identity.seatRef ||
|
|
56
|
+
onboarding.accountBinding !== bundle.provenance.accountBinding ||
|
|
57
|
+
onboarding.consent.ownerScope !== bundle.identity.ownerScope ||
|
|
58
|
+
onboarding.lineage.epoch !== lifecycle.epoch ||
|
|
59
|
+
onboarding.lineage.generation !== lifecycle.generation ||
|
|
60
|
+
onboarding.lineage.operationId !== lifecycle.operationId) {
|
|
61
|
+
fail('onboarding-lineage-mismatch', 'seat record binding mismatch');
|
|
62
|
+
}
|
|
63
|
+
if (bundle.identity.nativeCliVersion !== onboarding.nativeCliVersion) {
|
|
64
|
+
fail('onboarding-version-mismatch', 'record version mismatch');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (bundle.identity.ownerScope !== input.ownerScope) {
|
|
68
|
+
fail('onboarding-lineage-mismatch', 'ownerScope does not match the seat record');
|
|
69
|
+
}
|
|
70
|
+
if (bundle.identity.nativeCliVersion !== undefined && bundle.identity.nativeCliVersion !== input.expectedNativeCliVersion) {
|
|
71
|
+
fail('onboarding-version-mismatch', 'bundle nativeCliVersion does not match the expected version');
|
|
72
|
+
}
|
|
73
|
+
if (onboarding && onboarding.nativeCliVersion !== input.expectedNativeCliVersion) {
|
|
74
|
+
fail('onboarding-version-mismatch', 'block nativeCliVersion does not match the expected version');
|
|
75
|
+
}
|
|
76
|
+
const derivedGate = seatLaunchGate(cli, onboardingStatus);
|
|
77
|
+
if (JSON.stringify(record['launchGate']) !== JSON.stringify(derivedGate)) {
|
|
78
|
+
fail('onboarding-lineage-mismatch', 'stored launchGate disagrees with the re-derived gate');
|
|
79
|
+
}
|
|
80
|
+
const authFiles = record['authFiles'];
|
|
81
|
+
if (!Array.isArray(authFiles) || authFiles.some((n) => typeof n !== 'string')) {
|
|
82
|
+
fail('onboarding-schema-mismatch', 'seat record authFiles must be a string list');
|
|
83
|
+
}
|
|
84
|
+
return { bundle, onboarding, onboardingStatus, launchGate: derivedGate, authFiles: authFiles };
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=seat-onboarding-record.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seat-onboarding-record.js","sourceRoot":"","sources":["../../src/node/seat-onboarding-record.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SeatStageInput, SeatStageResult } from './seat-onboarding-types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Stage 1, batch and two-phase: phase 1 validates every envelope (bundle,
|
|
4
|
+
* agy tuple, auth allowlist, onboarding binding, versions, digests, size
|
|
5
|
+
* bounds, claude minimized projection) and refuses the whole batch on the
|
|
6
|
+
* first failure with zero bytes written; an absent block is valid and
|
|
7
|
+
* stages with a closed launch gate. Phase 2 writes auth files at their
|
|
8
|
+
* storage names plus the seat record, per seat.
|
|
9
|
+
*/
|
|
10
|
+
export declare function materialiseSeatEnvelopes(input: SeatStageInput): Promise<SeatStageResult>;
|
|
11
|
+
//# sourceMappingURL=seat-onboarding-stage1.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seat-onboarding-stage1.d.ts","sourceRoot":"","sources":["../../src/node/seat-onboarding-stage1.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,cAAc,EAGd,eAAe,EAChB,MAAM,4BAA4B,CAAC;AAkCpC;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CAoF9F"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Stage 1 (seat stage): batch two-phase materialization of validated seat
|
|
3
|
+
// envelopes into per-seat directories, plus the library-owned seat record.
|
|
4
|
+
import { chmod, lstat, mkdir } from 'node:fs/promises';
|
|
5
|
+
import { join, resolve } from 'node:path';
|
|
6
|
+
import { validateSeatEnvelope, } from '../enrollment/seat-onboarding.js';
|
|
7
|
+
import { SEAT_RECORD_REL_PATH, asResult, decodeBase64, fail, isRecord, sha256Hex, utf8, writeExclusive, assertCleanAncestors, DIR_MODE, } from './seat-stage-write.js';
|
|
8
|
+
/** Auth `.claude.json` minimized-projection key set (stage-1 check, §3.3). */
|
|
9
|
+
const CLAUDE_AUTH_MINIMIZED_KEYS = ['oauthAccount', 'hasCompletedOnboarding', 'lastOnboardingVersion'];
|
|
10
|
+
function checkClaudeAuthMinimized(files) {
|
|
11
|
+
const raw = files['.claude.json'];
|
|
12
|
+
if (raw === undefined)
|
|
13
|
+
return;
|
|
14
|
+
let obj;
|
|
15
|
+
try {
|
|
16
|
+
obj = JSON.parse(new TextDecoder().decode(decodeBase64(raw)));
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
fail('onboarding-shape-unverified', 'auth .claude.json is not JSON');
|
|
20
|
+
}
|
|
21
|
+
if (!isRecord(obj))
|
|
22
|
+
fail('onboarding-shape-unverified', 'auth .claude.json must be an object');
|
|
23
|
+
for (const key of Object.keys(obj)) {
|
|
24
|
+
if (!CLAUDE_AUTH_MINIMIZED_KEYS.includes(key)) {
|
|
25
|
+
fail('onboarding-shape-unverified', `non-minimized auth .claude.json key: ${key}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Stage 1, batch and two-phase: phase 1 validates every envelope (bundle,
|
|
31
|
+
* agy tuple, auth allowlist, onboarding binding, versions, digests, size
|
|
32
|
+
* bounds, claude minimized projection) and refuses the whole batch on the
|
|
33
|
+
* first failure with zero bytes written; an absent block is valid and
|
|
34
|
+
* stages with a closed launch gate. Phase 2 writes auth files at their
|
|
35
|
+
* storage names plus the seat record, per seat.
|
|
36
|
+
*/
|
|
37
|
+
export async function materialiseSeatEnvelopes(input) {
|
|
38
|
+
try {
|
|
39
|
+
if (!isRecord(input) || !Array.isArray(input['seats']) || input['seats'].length === 0) {
|
|
40
|
+
fail('schema-mismatch', 'seats must be a non-empty array');
|
|
41
|
+
}
|
|
42
|
+
const ownerScope = input['ownerScope'];
|
|
43
|
+
if (typeof ownerScope !== 'string' || ownerScope.length === 0)
|
|
44
|
+
fail('schema-mismatch', 'ownerScope is required');
|
|
45
|
+
const expectedVersions = (input['expectedNativeCliVersions'] ?? {});
|
|
46
|
+
const validated = [];
|
|
47
|
+
const seenDirs = new Set();
|
|
48
|
+
for (const seat of input['seats']) {
|
|
49
|
+
if (!isRecord(seat) || typeof seat['seatDir'] !== 'string' || seat['seatDir'].length === 0) {
|
|
50
|
+
fail('schema-mismatch', 'each seat needs a seatDir');
|
|
51
|
+
}
|
|
52
|
+
const seatDir = resolve(seat['seatDir']);
|
|
53
|
+
if (seenDirs.has(seatDir))
|
|
54
|
+
fail('schema-mismatch', 'duplicate seatDir in batch');
|
|
55
|
+
seenDirs.add(seatDir);
|
|
56
|
+
const env = validateSeatEnvelope(seat['envelope'], { trustedAuthority: 'consumer' });
|
|
57
|
+
if (!env.ok)
|
|
58
|
+
fail(env.code, env.detail);
|
|
59
|
+
const { bundle, files, onboarding, onboardingStatus, launchGate } = env;
|
|
60
|
+
if (bundle.identity.ownerScope !== ownerScope) {
|
|
61
|
+
fail('onboarding-lineage-mismatch', 'bundle ownerScope does not match the stage ownerScope');
|
|
62
|
+
}
|
|
63
|
+
const expected = expectedVersions[bundle.identity.cli];
|
|
64
|
+
if (expected !== undefined && bundle.identity.nativeCliVersion !== expected) {
|
|
65
|
+
fail('onboarding-version-mismatch', 'bundle nativeCliVersion does not match the expected version');
|
|
66
|
+
}
|
|
67
|
+
if (bundle.identity.cli === 'claude')
|
|
68
|
+
checkClaudeAuthMinimized(files);
|
|
69
|
+
const existing = await lstat(seatDir).catch(() => null);
|
|
70
|
+
if (existing)
|
|
71
|
+
fail('onboarding-shape-unverified', `seatDir already exists: ${seatDir}`);
|
|
72
|
+
await assertCleanAncestors(seatDir);
|
|
73
|
+
validated.push({ seatDir, bundle, files, onboarding, onboardingStatus, launchGate });
|
|
74
|
+
}
|
|
75
|
+
const seats = [];
|
|
76
|
+
for (const v of validated) {
|
|
77
|
+
await mkdir(v.seatDir, { recursive: true, mode: DIR_MODE });
|
|
78
|
+
await chmod(v.seatDir, DIR_MODE);
|
|
79
|
+
const authFiles = Object.keys(v.files).sort();
|
|
80
|
+
for (const name of authFiles) {
|
|
81
|
+
await writeExclusive([v.seatDir], join(v.seatDir, name), decodeBase64(v.files[name]));
|
|
82
|
+
}
|
|
83
|
+
const record = {
|
|
84
|
+
version: 1,
|
|
85
|
+
bundle: v.bundle,
|
|
86
|
+
onboarding: v.onboarding,
|
|
87
|
+
launchGate: v.launchGate,
|
|
88
|
+
authFiles,
|
|
89
|
+
};
|
|
90
|
+
const recordBytes = utf8(`${JSON.stringify(record, null, 2)}\n`);
|
|
91
|
+
await writeExclusive([v.seatDir], join(v.seatDir, SEAT_RECORD_REL_PATH), recordBytes);
|
|
92
|
+
seats.push({
|
|
93
|
+
seatRef: v.bundle.identity.seatRef,
|
|
94
|
+
cli: v.bundle.identity.cli,
|
|
95
|
+
authFiles,
|
|
96
|
+
seatRecordSha256: sha256Hex(recordBytes),
|
|
97
|
+
onboardingStatus: v.onboardingStatus,
|
|
98
|
+
launchGate: v.launchGate,
|
|
99
|
+
onboarding: v.onboarding
|
|
100
|
+
? {
|
|
101
|
+
files: v.onboarding.files.map((f) => ({
|
|
102
|
+
destKey: f.destKey,
|
|
103
|
+
format: f.format,
|
|
104
|
+
sha256: f.sha256,
|
|
105
|
+
byteLength: f.byteLength,
|
|
106
|
+
})),
|
|
107
|
+
nativeCliVersion: v.onboarding.nativeCliVersion,
|
|
108
|
+
capturedAt: v.onboarding.capturedAt,
|
|
109
|
+
lineage: v.onboarding.lineage,
|
|
110
|
+
...(v.onboarding.reboundFrom ? { reboundFrom: v.onboarding.reboundFrom } : {}),
|
|
111
|
+
}
|
|
112
|
+
: null,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
return { ok: true, receipt: { seats } };
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
return asResult(error);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=seat-onboarding-stage1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seat-onboarding-stage1.js","sourceRoot":"","sources":["../../src/node/seat-onboarding-stage1.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SeatCellInput, SeatCellResult } from './seat-onboarding-types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Stage 2, one seat into one fresh cell HOME. Re-reads and re-validates the
|
|
4
|
+
* seat record (binding + versions), re-derives the launch gate (a stored
|
|
5
|
+
* gate that disagrees is a tampered record), refuses a closed gate with
|
|
6
|
+
* `onboarding-required` before any write, then writes as single writer per
|
|
7
|
+
* owned destination. The seatDir is opened read-only and never mutated.
|
|
8
|
+
*/
|
|
9
|
+
export declare function materialiseCellHome(input: SeatCellInput): Promise<SeatCellResult>;
|
|
10
|
+
//# sourceMappingURL=seat-onboarding-stage2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seat-onboarding-stage2.d.ts","sourceRoot":"","sources":["../../src/node/seat-onboarding-stage2.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAEV,aAAa,EACb,cAAc,EAEf,MAAM,4BAA4B,CAAC;AAUpC;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAiFvF"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Stage 2 (cell stage): seed one fresh cell HOME from a staged seat record.
|
|
3
|
+
// Single writer per owned destination; the seatDir is opened read-only.
|
|
4
|
+
import { lstat, readdir, readFile } from 'node:fs/promises';
|
|
5
|
+
import { join, resolve } from 'node:path';
|
|
6
|
+
import { SEAT_ENVELOPE_AUTH_FILES } from '../enrollment/seat-onboarding.js';
|
|
7
|
+
import { authCellDest, planOnboardingWrites, receiptRelPath } from './seat-onboarding-cell-compose.js';
|
|
8
|
+
import { readSeatRecord } from './seat-onboarding-record.js';
|
|
9
|
+
import { asResult, fail, isRecord, sha256Hex, writeExclusive, assertCleanAncestors, } from './seat-stage-write.js';
|
|
10
|
+
/**
|
|
11
|
+
* Stage 2, one seat into one fresh cell HOME. Re-reads and re-validates the
|
|
12
|
+
* seat record (binding + versions), re-derives the launch gate (a stored
|
|
13
|
+
* gate that disagrees is a tampered record), refuses a closed gate with
|
|
14
|
+
* `onboarding-required` before any write, then writes as single writer per
|
|
15
|
+
* owned destination. The seatDir is opened read-only and never mutated.
|
|
16
|
+
*/
|
|
17
|
+
export async function materialiseCellHome(input) {
|
|
18
|
+
try {
|
|
19
|
+
if (!isRecord(input))
|
|
20
|
+
fail('schema-mismatch', 'input must be an object');
|
|
21
|
+
for (const key of ['seatDir', 'cellHome', 'workspaceDir', 'expectedNativeCliVersion', 'ownerScope']) {
|
|
22
|
+
if (typeof input[key] !== 'string' || input[key].length === 0)
|
|
23
|
+
fail('schema-mismatch', `${key} is required`);
|
|
24
|
+
}
|
|
25
|
+
if (!isRecord(input['configDirs']))
|
|
26
|
+
fail('schema-mismatch', 'configDirs is required');
|
|
27
|
+
const seatDir = resolve(input.seatDir);
|
|
28
|
+
const cellHome = resolve(input.cellHome);
|
|
29
|
+
const workspaceDir = resolve(input.workspaceDir);
|
|
30
|
+
const configDirs = {
|
|
31
|
+
claudeConfigDir: resolve(input.configDirs['claudeConfigDir']),
|
|
32
|
+
codexHome: resolve(input.configDirs['codexHome']),
|
|
33
|
+
xdgConfigHome: resolve(input.configDirs['xdgConfigHome']),
|
|
34
|
+
};
|
|
35
|
+
const record = await readSeatRecord({
|
|
36
|
+
seatDir,
|
|
37
|
+
expectedNativeCliVersion: input.expectedNativeCliVersion,
|
|
38
|
+
ownerScope: input.ownerScope,
|
|
39
|
+
});
|
|
40
|
+
const { bundle, onboarding, launchGate } = record;
|
|
41
|
+
const cli = bundle.identity.cli;
|
|
42
|
+
if (!launchGate.eligible)
|
|
43
|
+
fail('onboarding-required', 'launch gate is closed for this seat');
|
|
44
|
+
const wsSt = await lstat(workspaceDir).catch(() => null);
|
|
45
|
+
if (!wsSt || wsSt.isSymbolicLink() || !wsSt.isDirectory()) {
|
|
46
|
+
fail('onboarding-shape-unverified', 'workspaceDir must be an existing directory');
|
|
47
|
+
}
|
|
48
|
+
if (onboarding && onboarding.cellSynthesis.length > 0) {
|
|
49
|
+
// Q2: the trust write is allowed only for the bench-created empty workspace.
|
|
50
|
+
const entries = await readdir(workspaceDir);
|
|
51
|
+
if (entries.length > 0) {
|
|
52
|
+
fail('onboarding-shape-unverified', 'trust write is limited to the empty bench-created workspace (Q2)');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const cellSt = await lstat(cellHome).catch(() => null);
|
|
56
|
+
if (cellSt)
|
|
57
|
+
fail('onboarding-shape-unverified', 'cellHome must be fresh (not pre-existing)');
|
|
58
|
+
for (const dir of Object.values(configDirs)) {
|
|
59
|
+
const st = await lstat(dir).catch(() => null);
|
|
60
|
+
if (st)
|
|
61
|
+
fail('onboarding-shape-unverified', `configDir must be fresh: ${dir}`);
|
|
62
|
+
}
|
|
63
|
+
const roots = [cellHome, configDirs.claudeConfigDir, configDirs.codexHome, configDirs.xdgConfigHome];
|
|
64
|
+
for (const root of roots)
|
|
65
|
+
await assertCleanAncestors(root);
|
|
66
|
+
// plan every write before writing any byte
|
|
67
|
+
const writes = [];
|
|
68
|
+
const allowlist = SEAT_ENVELOPE_AUTH_FILES[cli];
|
|
69
|
+
for (const name of record.authFiles) {
|
|
70
|
+
if (!allowlist.includes(name))
|
|
71
|
+
fail('unknown-field', `auth file not allowlisted for ${cli}: ${name}`);
|
|
72
|
+
const src = join(seatDir, name);
|
|
73
|
+
const st = await lstat(src).catch(() => null);
|
|
74
|
+
if (!st || st.isSymbolicLink() || !st.isFile()) {
|
|
75
|
+
fail('onboarding-shape-unverified', `auth file missing in seatDir: ${name}`);
|
|
76
|
+
}
|
|
77
|
+
const bytes = new Uint8Array(await readFile(src));
|
|
78
|
+
if (cli === 'claude' && name === '.claude.json')
|
|
79
|
+
continue; // composed below
|
|
80
|
+
writes.push({ path: authCellDest(name, cellHome, configDirs), bytes, cls: 'auth' });
|
|
81
|
+
}
|
|
82
|
+
if (onboarding) {
|
|
83
|
+
writes.push(...await planOnboardingWrites({
|
|
84
|
+
cli,
|
|
85
|
+
onboarding,
|
|
86
|
+
seatDir,
|
|
87
|
+
cellHome,
|
|
88
|
+
workspaceDir,
|
|
89
|
+
configDirs,
|
|
90
|
+
claudeMcpConfig: input.claudeMcpConfig,
|
|
91
|
+
codexMcpServers: input.codexMcpServers,
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
for (const w of writes)
|
|
95
|
+
await writeExclusive(roots, w.path, w.bytes);
|
|
96
|
+
const files = writes
|
|
97
|
+
.map((w) => ({
|
|
98
|
+
cellRelPath: receiptRelPath(w.path, cellHome, configDirs),
|
|
99
|
+
class: w.cls,
|
|
100
|
+
sha256: sha256Hex(w.bytes),
|
|
101
|
+
byteLength: w.bytes.length,
|
|
102
|
+
}))
|
|
103
|
+
.sort((a, b) => a.cellRelPath.localeCompare(b.cellRelPath));
|
|
104
|
+
return { ok: true, receipt: { files } };
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
return asResult(error);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=seat-onboarding-stage2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seat-onboarding-stage2.js","sourceRoot":"","sources":["../../src/node/seat-onboarding-stage2.ts"],"names":[],"mappings":"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"}
|