@modelprofile.com/authswitch 6.4.0 → 7.0.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_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/authority-contract.d.ts +302 -6
- package/dist_ts/authority-contract.js +1 -1
- package/dist_ts/authority-runtime-contract.d.ts +15 -0
- package/dist_ts/authorityrehearsal.child.d.ts +1 -0
- package/dist_ts/authorityrehearsal.child.js +395 -0
- package/dist_ts/classes.accountlist.js +4 -3
- package/dist_ts/classes.authoritybackup.d.ts +134 -0
- package/dist_ts/classes.authoritybackup.js +769 -0
- package/dist_ts/classes.authoritybroker.d.ts +29 -6
- package/dist_ts/classes.authoritybroker.js +413 -122
- package/dist_ts/classes.authoritycli.d.ts +24 -0
- package/dist_ts/classes.authoritycli.js +675 -0
- package/dist_ts/classes.authorityclient.d.ts +34 -9
- package/dist_ts/classes.authorityclient.js +136 -38
- package/dist_ts/classes.authoritydaemon.d.ts +47 -0
- package/dist_ts/classes.authoritydaemon.js +705 -16
- package/dist_ts/classes.authoritydatabase.d.ts +182 -8
- package/dist_ts/classes.authoritydatabase.js +1188 -41
- package/dist_ts/classes.authoritymodels.d.ts +247 -1
- package/dist_ts/classes.authoritymodels.js +870 -6
- package/dist_ts/classes.authoritypreuse.d.ts +47 -0
- package/dist_ts/classes.authoritypreuse.js +278 -0
- package/dist_ts/classes.authorityregistry.d.ts +24 -0
- package/dist_ts/classes.authorityregistry.js +88 -0
- package/dist_ts/classes.authorityrehearsal.d.ts +127 -0
- package/dist_ts/classes.authorityrehearsal.js +632 -0
- package/dist_ts/classes.authorityusage.d.ts +160 -0
- package/dist_ts/classes.authorityusage.js +429 -0
- package/dist_ts/classes.claudeauthority.d.ts +66 -0
- package/dist_ts/classes.claudeauthority.js +532 -0
- package/dist_ts/classes.claudecodeharness.js +3 -2
- package/dist_ts/classes.claudecodelocks.d.ts +13 -0
- package/dist_ts/classes.claudecodelocks.js +75 -3
- package/dist_ts/classes.claudenative.d.ts +137 -0
- package/dist_ts/classes.claudenative.js +731 -0
- package/dist_ts/classes.claudestatus.d.ts +9 -0
- package/dist_ts/classes.claudestatus.js +26 -9
- package/dist_ts/classes.claudetokenrefresh.d.ts +15 -1
- package/dist_ts/classes.claudetokenrefresh.js +74 -21
- package/dist_ts/classes.codexharness.js +4 -2
- package/dist_ts/classes.codexmanaged.d.ts +91 -0
- package/dist_ts/classes.codexmanaged.js +404 -0
- package/dist_ts/classes.codexpreuse.d.ts +8 -0
- package/dist_ts/classes.codexpreuse.js +24 -6
- package/dist_ts/classes.fileharness.d.ts +2 -0
- package/dist_ts/classes.fileharness.js +6 -4
- package/dist_ts/classes.limits.js +12 -7
- package/dist_ts/classes.opencodeharness.js +2 -2
- package/dist_ts/claudehttp.d.ts +10 -0
- package/dist_ts/claudehttp.js +29 -3
- package/dist_ts/index.d.ts +2 -0
- package/dist_ts/index.js +8 -1
- package/dist_ts/interfaces.harness.d.ts +6 -0
- package/dist_ts/interfaces.list.d.ts +9 -3
- package/dist_ts/plugins.d.ts +7 -3
- package/dist_ts/plugins.js +9 -4
- package/dist_ts/ts_migration/0001_authority_meta.d.ts +3 -0
- package/dist_ts/ts_migration/0001_authority_meta.js +32 -0
- package/dist_ts/ts_migration/index.d.ts +3 -0
- package/dist_ts/ts_migration/index.js +6 -0
- package/package.json +12 -2
- package/readme.md +205 -13
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/authority-contract.ts +264 -9
- package/ts/authority-runtime-contract.ts +21 -1
- package/ts/authorityrehearsal.child.ts +330 -0
- package/ts/classes.accountlist.ts +3 -2
- package/ts/classes.authoritybackup.ts +780 -0
- package/ts/classes.authoritybroker.ts +410 -120
- package/ts/classes.authoritycli.ts +719 -0
- package/ts/classes.authorityclient.ts +164 -38
- package/ts/classes.authoritydaemon.ts +614 -17
- package/ts/classes.authoritydatabase.ts +1229 -44
- package/ts/classes.authoritymodels.ts +579 -4
- package/ts/classes.authoritypreuse.ts +297 -0
- package/ts/classes.authorityregistry.ts +118 -0
- package/ts/classes.authorityrehearsal.ts +625 -0
- package/ts/classes.authorityusage.ts +527 -0
- package/ts/classes.claudeauthority.ts +541 -0
- package/ts/classes.claudecodeharness.ts +2 -1
- package/ts/classes.claudecodelocks.ts +70 -1
- package/ts/classes.claudenative.ts +816 -0
- package/ts/classes.claudestatus.ts +38 -9
- package/ts/classes.claudetokenrefresh.ts +82 -19
- package/ts/classes.codexharness.ts +3 -1
- package/ts/classes.codexmanaged.ts +402 -0
- package/ts/classes.codexpreuse.ts +33 -5
- package/ts/classes.fileharness.ts +7 -3
- package/ts/classes.limits.ts +11 -6
- package/ts/classes.opencodeharness.ts +1 -1
- package/ts/claudehttp.ts +31 -2
- package/ts/index.ts +7 -0
- package/ts/interfaces.harness.ts +6 -0
- package/ts/interfaces.list.ts +9 -3
- package/ts/plugins.ts +9 -3
- package/ts/ts_migration/0001_authority_meta.ts +33 -0
- package/ts/ts_migration/index.ts +7 -0
|
@@ -0,0 +1,769 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { assertStoredAuthorityBinding, assertStoredAuthorityClaudeHandoff, assertStoredAuthorityClaudeHome, assertStoredAuthorityCodexHome, assertStoredAuthorityEnrollment, assertStoredAuthorityGrant, assertStoredAuthorityHandoff, assertStoredAuthorityMeta, assertStoredAuthorityMigrationLedger, assertStoredAuthorityOperation, restoreStoredAuthorityOperation, } from './classes.authoritymodels.js';
|
|
3
|
+
import { assertAuthorityStoredRecord } from './classes.authorityregistry.js';
|
|
4
|
+
const maxPlainChunkBytes = 8 * 1024 * 1024;
|
|
5
|
+
const maxEncryptedObjectBytes = 12 * 1024 * 1024;
|
|
6
|
+
// The manifest is still one object. A paged authenticated index is required for unlimited inventory.
|
|
7
|
+
const maxRecordBytes = 1024 * 1024;
|
|
8
|
+
const maxSourceBytes = 4 * 1024 * 1024;
|
|
9
|
+
const hash = (bytes) => plugins.crypto.createHash('sha256').update(bytes).digest('hex');
|
|
10
|
+
const uuid = () => plugins.crypto.randomUUID();
|
|
11
|
+
const isHash = (value) => typeof value === 'string' && /^[a-f0-9]{64}$/.test(value);
|
|
12
|
+
const isName = (value) => typeof value === 'string' && /^[a-zA-Z0-9_.:-]{1,256}$/.test(value);
|
|
13
|
+
const isDigestField = (value) => value === 'sourceDigest' || value === 'before.credentialDigest' || value === 'before.configDigest';
|
|
14
|
+
function fail(message) { throw new Error(message); }
|
|
15
|
+
const recordKey = (model, id) => `${model}\u0000${id}`;
|
|
16
|
+
const context = (...parts) => Buffer.from(JSON.stringify(['authswitch-backup-v1', ...parts]));
|
|
17
|
+
const object = (value) => value !== null
|
|
18
|
+
&& typeof value === 'object' && !Array.isArray(value)
|
|
19
|
+
&& [Object.prototype, null].includes(Object.getPrototypeOf(value));
|
|
20
|
+
const exactKeys = (value, keys) => Object.keys(value).length === keys.length && keys.every(key => Object.hasOwn(value, key));
|
|
21
|
+
const assertSnapshotRecord = assertAuthorityStoredRecord;
|
|
22
|
+
/** This ID preserves Codex's complete three-column enrollment key, without email matching. */
|
|
23
|
+
export const authorityEnrollmentId = (row) => hash(JSON.stringify(['authswitch-enrollment-v1', row.websocketUrl, row.accountId, row.appServerClientName]));
|
|
24
|
+
const parseEnrollment = (bytes, id) => {
|
|
25
|
+
const value = JSON.parse(Buffer.from(bytes).toString('utf8'));
|
|
26
|
+
if (!object(value) || !exactKeys(value, ['websocketUrl', 'accountId', 'appServerClientName',
|
|
27
|
+
'serverId', 'environmentId', 'serverName', 'updatedAt', 'remoteControlEnabled'])
|
|
28
|
+
|| !['websocketUrl', 'accountId', 'appServerClientName', 'serverId', 'environmentId', 'serverName']
|
|
29
|
+
.every(key => typeof value[key] === 'string')
|
|
30
|
+
|| !Number.isSafeInteger(value.updatedAt) || Number(value.updatedAt) < 0
|
|
31
|
+
|| ![null, 0, 1].includes(value.remoteControlEnabled)) {
|
|
32
|
+
throw new Error('Backup enrollment has an invalid or incomplete Codex row.');
|
|
33
|
+
}
|
|
34
|
+
const row = value;
|
|
35
|
+
if (!row.websocketUrl || !row.accountId
|
|
36
|
+
|| authorityEnrollmentId(row) !== id)
|
|
37
|
+
throw new Error('Backup enrollment composite identity changed.');
|
|
38
|
+
return row;
|
|
39
|
+
};
|
|
40
|
+
const assertJson = (value, depth = 0) => {
|
|
41
|
+
if (depth > 24)
|
|
42
|
+
fail('Backup record exceeds the JSON depth limit.');
|
|
43
|
+
if (value === null || typeof value === 'string' || typeof value === 'boolean')
|
|
44
|
+
return;
|
|
45
|
+
if (typeof value === 'number' && Number.isFinite(value))
|
|
46
|
+
return;
|
|
47
|
+
if (Array.isArray(value)) {
|
|
48
|
+
for (const item of value)
|
|
49
|
+
assertJson(item, depth + 1);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (object(value)) {
|
|
53
|
+
for (const item of Object.values(value))
|
|
54
|
+
assertJson(item, depth + 1);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
fail('Backup record contains a non-JSON value.');
|
|
58
|
+
};
|
|
59
|
+
/** SmartData readback may reorder object fields; arrays and native source bytes remain exact. */
|
|
60
|
+
const canonicalJson = (value) => {
|
|
61
|
+
if (Array.isArray(value))
|
|
62
|
+
return `[${value.map(canonicalJson).join(',')}]`;
|
|
63
|
+
if (object(value))
|
|
64
|
+
return `{${Object.keys(value).sort().map(key => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(',')}}`;
|
|
65
|
+
assertJson(value);
|
|
66
|
+
return JSON.stringify(value);
|
|
67
|
+
};
|
|
68
|
+
/** Thin adapter over SmartBucket's provider-probed, create-only exact upload API. */
|
|
69
|
+
export class AuthoritySmartBucketStore {
|
|
70
|
+
bucket;
|
|
71
|
+
capability;
|
|
72
|
+
constructor(bucket) {
|
|
73
|
+
this.bucket = bucket;
|
|
74
|
+
}
|
|
75
|
+
async prepare(signal) {
|
|
76
|
+
const result = await this.bucket.probeExactUploadCapability({ signal });
|
|
77
|
+
if (!result.supported)
|
|
78
|
+
throw new Error(`Exact backup uploads unavailable: ${result.reason}`);
|
|
79
|
+
this.capability = result.capability;
|
|
80
|
+
}
|
|
81
|
+
async putExact(path, bytes, signal) {
|
|
82
|
+
if (!this.capability)
|
|
83
|
+
throw new Error('Exact upload capability has not been probed.');
|
|
84
|
+
const source = plugins.stream.Readable.from((function* () {
|
|
85
|
+
for (let offset = 0; offset < bytes.byteLength; offset += 1024 * 1024) {
|
|
86
|
+
yield Buffer.from(bytes.subarray(offset, offset + 1024 * 1024));
|
|
87
|
+
}
|
|
88
|
+
})());
|
|
89
|
+
try {
|
|
90
|
+
await this.bucket.fastPutStreamExact({ capability: this.capability, path, readableStream: source,
|
|
91
|
+
contentLength: bytes.byteLength, nativeObjectProperties: { contentType: 'application/json' }, signal });
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
source.destroy();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async get(path, maxBytes, signal) {
|
|
98
|
+
const source = await this.bucket.fastGetStream({ path, signal });
|
|
99
|
+
const chunks = [];
|
|
100
|
+
let length = 0;
|
|
101
|
+
try {
|
|
102
|
+
for await (const chunk of source) {
|
|
103
|
+
const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
104
|
+
length += bytes.byteLength;
|
|
105
|
+
if (length > maxBytes)
|
|
106
|
+
throw new Error('Backup object exceeds its bounded read limit.');
|
|
107
|
+
chunks.push(bytes);
|
|
108
|
+
}
|
|
109
|
+
return Buffer.concat(chunks, length);
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
source.destroy();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function assertManifest(value, backupId, prefix) {
|
|
117
|
+
if (!object(value) || !exactKeys(value, ['schemaVersion', 'backupId', 'epoch', 'revision',
|
|
118
|
+
'recipientKeyId', 'chunks', 'recordCount', 'sources', 'snapshotDigest'])
|
|
119
|
+
|| value.schemaVersion !== 1 || value.backupId !== backupId
|
|
120
|
+
|| typeof value.epoch !== 'string' || !/^[a-f0-9-]{36}$/.test(value.epoch)
|
|
121
|
+
|| !Number.isSafeInteger(value.revision) || Number(value.revision) < 0
|
|
122
|
+
|| !isName(value.recipientKeyId) || !Number.isSafeInteger(value.recordCount)
|
|
123
|
+
|| Number(value.recordCount) < 1 || !isHash(value.snapshotDigest)
|
|
124
|
+
|| !Array.isArray(value.chunks) || !Array.isArray(value.sources)) {
|
|
125
|
+
fail('Invalid authenticated backup manifest.');
|
|
126
|
+
}
|
|
127
|
+
for (let index = 0; index < value.chunks.length; index++) {
|
|
128
|
+
const item = value.chunks[index];
|
|
129
|
+
if (!object(item) || !exactKeys(item, ['sequence', 'path', 'encryptedDigest',
|
|
130
|
+
'plaintextDigest', 'length', 'entries']) || item.sequence !== index
|
|
131
|
+
|| item.path !== `${prefix}/${backupId}/chunk-${String(index).padStart(5, '0')}.json`
|
|
132
|
+
|| !isHash(item.encryptedDigest) || !isHash(item.plaintextDigest)
|
|
133
|
+
|| !Number.isSafeInteger(item.length) || Number(item.length) < 1
|
|
134
|
+
|| Number(item.length) > maxEncryptedObjectBytes
|
|
135
|
+
|| !Number.isSafeInteger(item.entries) || Number(item.entries) < 1) {
|
|
136
|
+
fail('Invalid authenticated backup chunk index.');
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const sourceIds = new Set();
|
|
140
|
+
for (const item of value.sources) {
|
|
141
|
+
if (!object(item) || !exactKeys(item, ['kind', 'id', 'linkedModel', 'linkedId', 'linkedDigestField', 'digest'])
|
|
142
|
+
|| !isName(item.kind) || !isName(item.id) || !isName(item.linkedModel)
|
|
143
|
+
|| !isName(item.linkedId) || !isDigestField(item.linkedDigestField) || !isHash(item.digest)) {
|
|
144
|
+
fail('Invalid authenticated backup source index.');
|
|
145
|
+
}
|
|
146
|
+
const sourceKey = recordKey(item.kind, item.id);
|
|
147
|
+
if (sourceIds.has(sourceKey))
|
|
148
|
+
fail('Duplicate authenticated backup source proof.');
|
|
149
|
+
sourceIds.add(sourceKey);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
export class AuthorityBackupPublicationUnknownError extends Error {
|
|
153
|
+
path;
|
|
154
|
+
constructor(path, cause) {
|
|
155
|
+
super('Backup exact upload outcome could not be reconciled by readback.', { cause });
|
|
156
|
+
this.path = path;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/** Portable backup codec; the daemon's SmartData repository supplies the snapshot and persists the verified receipt. */
|
|
160
|
+
export class AuthSwitchAuthorityBackup {
|
|
161
|
+
options;
|
|
162
|
+
constructor(options) {
|
|
163
|
+
this.options = options;
|
|
164
|
+
}
|
|
165
|
+
publisher() {
|
|
166
|
+
if (!('source' in this.options))
|
|
167
|
+
fail('Backup publisher requires a committed snapshot source.');
|
|
168
|
+
return this.options;
|
|
169
|
+
}
|
|
170
|
+
verifier() {
|
|
171
|
+
if (!('rehearsal' in this.options))
|
|
172
|
+
fail('Backup verifier requires an isolated restore target.');
|
|
173
|
+
return this.options;
|
|
174
|
+
}
|
|
175
|
+
async secretFor(record) {
|
|
176
|
+
const value = record.value;
|
|
177
|
+
let id = null;
|
|
178
|
+
let sealed = null;
|
|
179
|
+
if (record.model === 'authswitch_authority_grants') {
|
|
180
|
+
assertStoredAuthorityGrant(value);
|
|
181
|
+
id = value.id;
|
|
182
|
+
sealed = value.ciphertext;
|
|
183
|
+
}
|
|
184
|
+
else if (record.model === 'authswitch_authority_enrollments') {
|
|
185
|
+
assertStoredAuthorityEnrollment(value);
|
|
186
|
+
id = value.id;
|
|
187
|
+
sealed = value.ciphertext;
|
|
188
|
+
}
|
|
189
|
+
else if (record.model === 'authswitch_authority_claude_handoffs' && object(value)
|
|
190
|
+
&& typeof value.outgoingGrantId === 'string' && typeof value.sealedOutgoing === 'string') {
|
|
191
|
+
id = value.outgoingGrantId;
|
|
192
|
+
sealed = value.sealedOutgoing;
|
|
193
|
+
}
|
|
194
|
+
if (!id || !sealed)
|
|
195
|
+
return null;
|
|
196
|
+
const bytes = await this.options.secrets.unseal(id, sealed);
|
|
197
|
+
try {
|
|
198
|
+
if (record.model === 'authswitch_authority_enrollments')
|
|
199
|
+
parseEnrollment(bytes, record.id);
|
|
200
|
+
return Buffer.from(bytes).toString('base64url');
|
|
201
|
+
}
|
|
202
|
+
finally {
|
|
203
|
+
bytes.fill(0);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
sourceDigestInRecord(record, field) {
|
|
207
|
+
if (!object(record.value))
|
|
208
|
+
return null;
|
|
209
|
+
if (field === 'sourceDigest')
|
|
210
|
+
return isHash(record.value.sourceDigest) ? record.value.sourceDigest : null;
|
|
211
|
+
if (object(record.value.before)) {
|
|
212
|
+
const digest = field === 'before.credentialDigest'
|
|
213
|
+
? record.value.before.credentialDigest : record.value.before.configDigest;
|
|
214
|
+
return isHash(digest) ? digest : null;
|
|
215
|
+
}
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
assertPreparedClaudeSourceCoverage(record, sources) {
|
|
219
|
+
if (record.model !== 'authswitch_authority_claude_handoffs')
|
|
220
|
+
return;
|
|
221
|
+
assertStoredAuthorityClaudeHandoff(record.value);
|
|
222
|
+
if (record.value.phase !== 'prepared')
|
|
223
|
+
return;
|
|
224
|
+
for (const field of ['before.credentialDigest', 'before.configDigest']) {
|
|
225
|
+
const digest = this.sourceDigestInRecord(record, field);
|
|
226
|
+
if (digest !== null && !sources.some(source => source.linkedDigestField === field && source.digest === digest)) {
|
|
227
|
+
fail('Prepared Claude native source bytes are missing from the backup.');
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
async stage(backupId, attempt) {
|
|
232
|
+
const publisher = this.publisher();
|
|
233
|
+
if (typeof attempt.epoch !== 'string' || !/^[a-f0-9-]{36}$/.test(attempt.epoch)
|
|
234
|
+
|| !Number.isSafeInteger(attempt.revision) || attempt.revision < 0)
|
|
235
|
+
fail('Invalid backup snapshot identity.');
|
|
236
|
+
const dir = await plugins.fs.promises.mkdtemp(plugins.path.join(plugins.os.tmpdir(), 'authswitch-backup-'));
|
|
237
|
+
await plugins.fs.promises.chmod(dir, 0o700);
|
|
238
|
+
const sources = [];
|
|
239
|
+
const sourceIds = new Set();
|
|
240
|
+
const sourceLinks = new Map();
|
|
241
|
+
const lines = [];
|
|
242
|
+
const chunks = [];
|
|
243
|
+
const snapshotHash = plugins.crypto.createHash('sha256');
|
|
244
|
+
let chunkBytes = 0;
|
|
245
|
+
let recordCount = 0;
|
|
246
|
+
let metaCount = 0;
|
|
247
|
+
let lastRecordKey = '';
|
|
248
|
+
const append = async (line) => {
|
|
249
|
+
const encoded = `${JSON.stringify(line)}\n`;
|
|
250
|
+
const length = Buffer.byteLength(encoded);
|
|
251
|
+
if (length > maxPlainChunkBytes)
|
|
252
|
+
fail('Backup entry exceeds the encrypted chunk limit.');
|
|
253
|
+
if (chunkBytes + length > maxPlainChunkBytes)
|
|
254
|
+
await flush();
|
|
255
|
+
lines.push(encoded);
|
|
256
|
+
chunkBytes += length;
|
|
257
|
+
snapshotHash.update(encoded);
|
|
258
|
+
};
|
|
259
|
+
const flush = async () => {
|
|
260
|
+
if (lines.length === 0)
|
|
261
|
+
return;
|
|
262
|
+
const sequence = chunks.length;
|
|
263
|
+
const plaintext = Buffer.from(lines.join(''));
|
|
264
|
+
const plaintextDigest = hash(plaintext);
|
|
265
|
+
try {
|
|
266
|
+
const envelope = await plugins.smartcrypto.sealX25519Envelope({ plaintext,
|
|
267
|
+
recipientPublicKey: publisher.recipientPublicKey, recipientKeyId: this.options.recipientKeyId,
|
|
268
|
+
context: context('chunk', backupId, attempt.epoch, attempt.revision, sequence, plaintextDigest) });
|
|
269
|
+
const encrypted = Buffer.from(JSON.stringify(envelope));
|
|
270
|
+
if (encrypted.byteLength > maxEncryptedObjectBytes)
|
|
271
|
+
fail('Encrypted backup chunk exceeds its object bound.');
|
|
272
|
+
const path = `${this.options.prefix}/${backupId}/chunk-${String(sequence).padStart(5, '0')}.json`;
|
|
273
|
+
await plugins.fs.promises.writeFile(plugins.path.join(dir, `${sequence}.enc`), encrypted, { flag: 'wx', mode: 0o600 });
|
|
274
|
+
chunks.push({ sequence, path, encryptedDigest: hash(encrypted), plaintextDigest,
|
|
275
|
+
length: encrypted.byteLength, entries: lines.length });
|
|
276
|
+
lines.length = 0;
|
|
277
|
+
chunkBytes = 0;
|
|
278
|
+
}
|
|
279
|
+
finally {
|
|
280
|
+
plaintext.fill(0);
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
try {
|
|
284
|
+
for await (const source of attempt.sources) {
|
|
285
|
+
this.options.signal?.throwIfAborted();
|
|
286
|
+
if (!isName(source.kind) || !isName(source.id)
|
|
287
|
+
|| !isName(source.linkedModel) || !isName(source.linkedId)
|
|
288
|
+
|| !isDigestField(source.linkedDigestField)
|
|
289
|
+
|| !(source.bytes instanceof Uint8Array) || source.bytes.byteLength === 0
|
|
290
|
+
|| source.bytes.byteLength > maxSourceBytes)
|
|
291
|
+
fail('Invalid or oversized exact-source capsule.');
|
|
292
|
+
const sourceKey = recordKey(source.kind, source.id);
|
|
293
|
+
if (sourceIds.has(sourceKey))
|
|
294
|
+
fail('Duplicate exact-source capsule.');
|
|
295
|
+
const bytes = Uint8Array.from(source.bytes);
|
|
296
|
+
try {
|
|
297
|
+
const proof = { kind: source.kind, id: source.id, linkedModel: source.linkedModel,
|
|
298
|
+
linkedId: source.linkedId, linkedDigestField: source.linkedDigestField,
|
|
299
|
+
digest: hash(bytes), seen: false };
|
|
300
|
+
await append({ kind: 'source', sourceKind: proof.kind, sourceId: proof.id,
|
|
301
|
+
linkedModel: proof.linkedModel, linkedId: proof.linkedId,
|
|
302
|
+
linkedDigestField: proof.linkedDigestField,
|
|
303
|
+
sourceDigest: proof.digest, payload: Buffer.from(bytes).toString('base64url') });
|
|
304
|
+
sources.push(proof);
|
|
305
|
+
sourceIds.add(sourceKey);
|
|
306
|
+
const linkKey = recordKey(proof.linkedModel, proof.linkedId);
|
|
307
|
+
const linked = sourceLinks.get(linkKey) ?? [];
|
|
308
|
+
linked.push(proof);
|
|
309
|
+
sourceLinks.set(linkKey, linked);
|
|
310
|
+
}
|
|
311
|
+
finally {
|
|
312
|
+
bytes.fill(0);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
for await (const record of attempt.records) {
|
|
316
|
+
this.options.signal?.throwIfAborted();
|
|
317
|
+
if (!isName(record.model) || !isName(record.id) || !object(record.value)
|
|
318
|
+
|| record.value.id !== record.id)
|
|
319
|
+
fail('Invalid backup record identity.');
|
|
320
|
+
const key = recordKey(record.model, record.id);
|
|
321
|
+
if (key <= lastRecordKey)
|
|
322
|
+
fail('Backup records must be sorted by model and stable ID.');
|
|
323
|
+
lastRecordKey = key;
|
|
324
|
+
assertJson(record.value);
|
|
325
|
+
if (Buffer.byteLength(JSON.stringify(record.value)) > maxRecordBytes)
|
|
326
|
+
fail('Backup record exceeds its size bound.');
|
|
327
|
+
assertSnapshotRecord(record);
|
|
328
|
+
if (record.model === 'authswitch_authority_meta') {
|
|
329
|
+
assertStoredAuthorityMeta(record.value);
|
|
330
|
+
if (record.value.epoch !== attempt.epoch || record.value.revision !== attempt.revision) {
|
|
331
|
+
fail('Backup metadata does not match the pinned snapshot.');
|
|
332
|
+
}
|
|
333
|
+
metaCount++;
|
|
334
|
+
}
|
|
335
|
+
for (const source of sourceLinks.get(key) ?? []) {
|
|
336
|
+
if (this.sourceDigestInRecord(record, source.linkedDigestField) !== source.digest) {
|
|
337
|
+
fail('Exact-source bytes differ from their linked persisted record.');
|
|
338
|
+
}
|
|
339
|
+
source.seen = true;
|
|
340
|
+
}
|
|
341
|
+
this.assertPreparedClaudeSourceCoverage(record, sourceLinks.get(key) ?? []);
|
|
342
|
+
await append({ kind: 'record', model: record.model, id: record.id,
|
|
343
|
+
value: record.value, secret: await this.secretFor(record) });
|
|
344
|
+
recordCount++;
|
|
345
|
+
}
|
|
346
|
+
if (metaCount !== 1 || sources.some(source => !source.seen)) {
|
|
347
|
+
fail('Backup is missing metadata or an exact-source linkage.');
|
|
348
|
+
}
|
|
349
|
+
await flush();
|
|
350
|
+
return { dir, manifest: { schemaVersion: 1, backupId, epoch: attempt.epoch,
|
|
351
|
+
revision: attempt.revision, recipientKeyId: this.options.recipientKeyId, chunks,
|
|
352
|
+
recordCount, sources: sources.map(source => ({ kind: source.kind, id: source.id,
|
|
353
|
+
linkedModel: source.linkedModel, linkedId: source.linkedId,
|
|
354
|
+
linkedDigestField: source.linkedDigestField, digest: source.digest })),
|
|
355
|
+
snapshotDigest: snapshotHash.digest('hex') } };
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
await plugins.fs.promises.rm(dir, { recursive: true, force: true });
|
|
359
|
+
throw error;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
async publish(path, bytes) {
|
|
363
|
+
try {
|
|
364
|
+
await this.options.store.putExact(path, bytes, this.options.signal);
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
if (!(error instanceof plugins.smartbucket.ExactUploadError)
|
|
368
|
+
|| error.state.destinationPublication !== 'ambiguous')
|
|
369
|
+
throw error;
|
|
370
|
+
let found;
|
|
371
|
+
try {
|
|
372
|
+
found = await this.options.store.get(path, bytes.byteLength, AbortSignal.timeout(30_000));
|
|
373
|
+
}
|
|
374
|
+
catch (readError) {
|
|
375
|
+
throw new AuthorityBackupPublicationUnknownError(path, readError);
|
|
376
|
+
}
|
|
377
|
+
if (hash(found) !== hash(bytes) || found.byteLength !== bytes.byteLength) {
|
|
378
|
+
throw new AuthorityBackupPublicationUnknownError(path, error);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
const readback = await this.options.store.get(path, bytes.byteLength, this.options.signal);
|
|
382
|
+
if (readback.byteLength !== bytes.byteLength || hash(readback) !== hash(bytes)) {
|
|
383
|
+
fail('Exact backup object readback differs from the published bytes.');
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
async publishSnapshot() {
|
|
387
|
+
const { source, recipientPublicKey } = this.publisher();
|
|
388
|
+
const { store, prefix, recipientKeyId } = this.options;
|
|
389
|
+
if (!/^[a-zA-Z0-9/_-]{1,256}$/.test(prefix) || prefix.startsWith('/') || prefix.endsWith('/')
|
|
390
|
+
|| prefix.includes('//') || !isName(recipientKeyId)
|
|
391
|
+
|| recipientPublicKey.byteLength !== 32) {
|
|
392
|
+
fail('Invalid backup destination or recovery-key reference.');
|
|
393
|
+
}
|
|
394
|
+
const backupId = uuid();
|
|
395
|
+
const stageHolder = { current: null };
|
|
396
|
+
try {
|
|
397
|
+
await source.capture(async (attempt) => {
|
|
398
|
+
if (stageHolder.current)
|
|
399
|
+
await plugins.fs.promises.rm(stageHolder.current.dir, { recursive: true, force: true });
|
|
400
|
+
stageHolder.current = null;
|
|
401
|
+
stageHolder.current = await this.stage(backupId, attempt);
|
|
402
|
+
});
|
|
403
|
+
const completed = stageHolder.current;
|
|
404
|
+
if (!completed)
|
|
405
|
+
fail('Snapshot source committed without a backup attempt.');
|
|
406
|
+
const manifestBytes = Buffer.from(JSON.stringify(completed.manifest));
|
|
407
|
+
if (manifestBytes.byteLength > maxRecordBytes)
|
|
408
|
+
fail('Backup manifest exceeds its size bound.');
|
|
409
|
+
const manifestEnvelope = await plugins.smartcrypto.sealX25519Envelope({
|
|
410
|
+
plaintext: manifestBytes, recipientPublicKey, recipientKeyId, context: context('manifest', backupId),
|
|
411
|
+
});
|
|
412
|
+
manifestBytes.fill(0);
|
|
413
|
+
const encryptedManifest = Buffer.from(JSON.stringify(manifestEnvelope));
|
|
414
|
+
const manifestPath = `${prefix}/${backupId}/manifest.json`;
|
|
415
|
+
await store.prepare(this.options.signal);
|
|
416
|
+
for (const chunk of completed.manifest.chunks) {
|
|
417
|
+
this.options.signal?.throwIfAborted();
|
|
418
|
+
const bytes = await plugins.fs.promises.readFile(plugins.path.join(completed.dir, `${chunk.sequence}.enc`));
|
|
419
|
+
if (bytes.byteLength !== chunk.length || hash(bytes) !== chunk.encryptedDigest) {
|
|
420
|
+
fail('Disposable encrypted backup staging changed before publication.');
|
|
421
|
+
}
|
|
422
|
+
await this.publish(chunk.path, bytes);
|
|
423
|
+
}
|
|
424
|
+
await this.publish(manifestPath, encryptedManifest);
|
|
425
|
+
return { backupId, manifestPath, manifestDigest: hash(encryptedManifest),
|
|
426
|
+
sourceEpoch: completed.manifest.epoch, sourceRevision: completed.manifest.revision,
|
|
427
|
+
snapshotDigest: completed.manifest.snapshotDigest };
|
|
428
|
+
}
|
|
429
|
+
finally {
|
|
430
|
+
if (stageHolder.current)
|
|
431
|
+
await plugins.fs.promises.rm(stageHolder.current.dir, { recursive: true, force: true });
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
/** Rehearse a previously published object set; no caller-supplied success flag is accepted. */
|
|
435
|
+
async rehearsePublished(input) {
|
|
436
|
+
if (!/^[a-f0-9-]{36}$/.test(input.backupId) || !isHash(input.manifestDigest)
|
|
437
|
+
|| !/^[a-f0-9-]{36}$/.test(input.sourceEpoch)
|
|
438
|
+
|| !Number.isSafeInteger(input.sourceRevision) || input.sourceRevision < 0
|
|
439
|
+
|| !isHash(input.snapshotDigest)
|
|
440
|
+
|| input.manifestPath !== `${this.options.prefix}/${input.backupId}/manifest.json`) {
|
|
441
|
+
fail('Invalid published backup reference.');
|
|
442
|
+
}
|
|
443
|
+
return this.verifyPublished(input);
|
|
444
|
+
}
|
|
445
|
+
async verifyPublished(input) {
|
|
446
|
+
const verifier = this.verifier();
|
|
447
|
+
const encrypted = await this.options.store.get(input.manifestPath, maxEncryptedObjectBytes, this.options.signal);
|
|
448
|
+
if (hash(encrypted) !== input.manifestDigest)
|
|
449
|
+
fail('Backup manifest readback digest changed.');
|
|
450
|
+
const opened = await plugins.smartcrypto.openX25519Envelope({
|
|
451
|
+
envelope: JSON.parse(Buffer.from(encrypted).toString('utf8')),
|
|
452
|
+
recipientPrivateKey: verifier.recipientPrivateKey,
|
|
453
|
+
expectedRecipientKeyId: this.options.recipientKeyId,
|
|
454
|
+
context: context('manifest', input.backupId),
|
|
455
|
+
});
|
|
456
|
+
let manifestValue;
|
|
457
|
+
try {
|
|
458
|
+
if (opened.byteLength > maxRecordBytes)
|
|
459
|
+
fail('Authenticated backup manifest exceeds its size bound.');
|
|
460
|
+
manifestValue = JSON.parse(Buffer.from(opened).toString('utf8'));
|
|
461
|
+
}
|
|
462
|
+
finally {
|
|
463
|
+
opened.fill(0);
|
|
464
|
+
}
|
|
465
|
+
assertManifest(manifestValue, input.backupId, this.options.prefix);
|
|
466
|
+
const manifest = manifestValue;
|
|
467
|
+
if (manifest.recipientKeyId !== this.options.recipientKeyId
|
|
468
|
+
|| manifest.epoch !== input.sourceEpoch || manifest.revision !== input.sourceRevision
|
|
469
|
+
|| manifest.snapshotDigest !== input.snapshotDigest) {
|
|
470
|
+
fail('Authenticated backup manifest does not match the committed snapshot.');
|
|
471
|
+
}
|
|
472
|
+
const sourceLinks = new Map();
|
|
473
|
+
manifest.sources.forEach((proof, index) => {
|
|
474
|
+
const key = recordKey(proof.linkedModel, proof.linkedId);
|
|
475
|
+
const linked = sourceLinks.get(key) ?? [];
|
|
476
|
+
linked.push({ proof, index });
|
|
477
|
+
sourceLinks.set(key, linked);
|
|
478
|
+
});
|
|
479
|
+
const linkedSourceIndexes = new Set();
|
|
480
|
+
const restoredEpoch = uuid();
|
|
481
|
+
const snapshotHash = plugins.crypto.createHash('sha256');
|
|
482
|
+
const expectedRecordHash = plugins.crypto.createHash('sha256');
|
|
483
|
+
const expectedSourceHash = plugins.crypto.createHash('sha256');
|
|
484
|
+
let recordCount = 0;
|
|
485
|
+
let sourceCount = 0;
|
|
486
|
+
let expectedCount = 0;
|
|
487
|
+
let expectedSourceCount = 0;
|
|
488
|
+
let lastKey = '';
|
|
489
|
+
let recordsStarted = false;
|
|
490
|
+
let fullyConsumed = false;
|
|
491
|
+
const self = this;
|
|
492
|
+
const entries = async function* () {
|
|
493
|
+
for (const chunk of manifest.chunks) {
|
|
494
|
+
self.options.signal?.throwIfAborted();
|
|
495
|
+
const encryptedChunk = await self.options.store.get(chunk.path, maxEncryptedObjectBytes, self.options.signal);
|
|
496
|
+
if (encryptedChunk.byteLength !== chunk.length || hash(encryptedChunk) !== chunk.encryptedDigest) {
|
|
497
|
+
fail('Published backup chunk differs from its authenticated manifest.');
|
|
498
|
+
}
|
|
499
|
+
const plaintext = await plugins.smartcrypto.openX25519Envelope({
|
|
500
|
+
envelope: JSON.parse(Buffer.from(encryptedChunk).toString('utf8')),
|
|
501
|
+
recipientPrivateKey: verifier.recipientPrivateKey,
|
|
502
|
+
expectedRecipientKeyId: manifest.recipientKeyId,
|
|
503
|
+
context: context('chunk', manifest.backupId, manifest.epoch, manifest.revision, chunk.sequence, chunk.plaintextDigest),
|
|
504
|
+
});
|
|
505
|
+
try {
|
|
506
|
+
if (plaintext.byteLength > maxPlainChunkBytes || hash(plaintext) !== chunk.plaintextDigest) {
|
|
507
|
+
fail('Published backup chunk plaintext digest changed.');
|
|
508
|
+
}
|
|
509
|
+
const serialized = Buffer.from(plaintext).toString('utf8');
|
|
510
|
+
if (!serialized.endsWith('\n'))
|
|
511
|
+
fail('Backup chunk ended with a truncated entry.');
|
|
512
|
+
const lines = serialized.slice(0, -1).split('\n');
|
|
513
|
+
if (lines.length !== chunk.entries)
|
|
514
|
+
fail('Backup chunk entry count changed.');
|
|
515
|
+
snapshotHash.update(serialized);
|
|
516
|
+
for (const line of lines) {
|
|
517
|
+
const entry = JSON.parse(line);
|
|
518
|
+
if (!object(entry))
|
|
519
|
+
fail('Invalid backup entry.');
|
|
520
|
+
if (entry.kind === 'source') {
|
|
521
|
+
if (recordsStarted)
|
|
522
|
+
fail('Exact-source capsules must precede backup records.');
|
|
523
|
+
if (!isName(entry.sourceKind) || !isName(entry.sourceId)
|
|
524
|
+
|| !isName(entry.linkedModel) || !isName(entry.linkedId)
|
|
525
|
+
|| !isDigestField(entry.linkedDigestField)
|
|
526
|
+
|| !isHash(entry.sourceDigest) || typeof entry.payload !== 'string') {
|
|
527
|
+
fail('Invalid exact-source backup capsule.');
|
|
528
|
+
}
|
|
529
|
+
const bytes = Buffer.from(entry.payload, 'base64url');
|
|
530
|
+
if (bytes.byteLength > maxSourceBytes || hash(bytes) !== entry.sourceDigest) {
|
|
531
|
+
fail('Exact-source capsule digest changed.');
|
|
532
|
+
}
|
|
533
|
+
const proof = manifest.sources[sourceCount];
|
|
534
|
+
if (!proof || proof.kind !== entry.sourceKind || proof.id !== entry.sourceId
|
|
535
|
+
|| proof.linkedModel !== entry.linkedModel || proof.linkedId !== entry.linkedId
|
|
536
|
+
|| proof.linkedDigestField !== entry.linkedDigestField
|
|
537
|
+
|| proof.digest !== entry.sourceDigest)
|
|
538
|
+
fail('Exact-source capsule order or coverage changed.');
|
|
539
|
+
sourceCount++;
|
|
540
|
+
const restored = { kind: 'source', sourceKind: entry.sourceKind,
|
|
541
|
+
sourceId: entry.sourceId, linkedModel: entry.linkedModel, linkedId: entry.linkedId,
|
|
542
|
+
linkedDigestField: entry.linkedDigestField, sourceDigest: entry.sourceDigest, bytes };
|
|
543
|
+
expectedSourceHash.update(canonicalJson({ ...restored,
|
|
544
|
+
bytes: Buffer.from(bytes).toString('base64url') }) + '\n');
|
|
545
|
+
expectedSourceCount++;
|
|
546
|
+
yield restored;
|
|
547
|
+
}
|
|
548
|
+
else if (entry.kind === 'record') {
|
|
549
|
+
recordsStarted = true;
|
|
550
|
+
if (!isName(entry.model) || !isName(entry.id) || !object(entry.value)
|
|
551
|
+
|| entry.value.id !== entry.id || (entry.secret !== null && typeof entry.secret !== 'string')) {
|
|
552
|
+
fail('Invalid backup record entry.');
|
|
553
|
+
}
|
|
554
|
+
const key = recordKey(entry.model, entry.id);
|
|
555
|
+
if (key <= lastKey)
|
|
556
|
+
fail('Backup record order changed.');
|
|
557
|
+
lastKey = key;
|
|
558
|
+
recordCount++;
|
|
559
|
+
const originalRecord = { model: entry.model, id: entry.id, value: entry.value };
|
|
560
|
+
assertSnapshotRecord(originalRecord);
|
|
561
|
+
const linked = sourceLinks.get(key) ?? [];
|
|
562
|
+
for (const { proof, index } of linked) {
|
|
563
|
+
if (self.sourceDigestInRecord(originalRecord, proof.linkedDigestField) !== proof.digest) {
|
|
564
|
+
fail('Authenticated source proof is not linked to its exact record digest.');
|
|
565
|
+
}
|
|
566
|
+
linkedSourceIndexes.add(index);
|
|
567
|
+
}
|
|
568
|
+
self.assertPreparedClaudeSourceCoverage(originalRecord, linked.map(item => item.proof));
|
|
569
|
+
const restored = await self.restoreRecord({ model: entry.model, id: entry.id,
|
|
570
|
+
value: entry.value }, entry.secret, restoredEpoch);
|
|
571
|
+
if (restored) {
|
|
572
|
+
expectedRecordHash.update(canonicalJson(restored) + '\n');
|
|
573
|
+
expectedCount++;
|
|
574
|
+
yield restored;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
else
|
|
578
|
+
fail('Unknown backup entry kind.');
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
finally {
|
|
582
|
+
plaintext.fill(0);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
if (linkedSourceIndexes.size !== manifest.sources.length) {
|
|
586
|
+
fail('Authenticated source proof lacks a linked persisted record.');
|
|
587
|
+
}
|
|
588
|
+
if (recordCount !== manifest.recordCount || sourceCount !== manifest.sources.length
|
|
589
|
+
|| snapshotHash.digest('hex') !== manifest.snapshotDigest) {
|
|
590
|
+
fail('Published backup snapshot is incomplete.');
|
|
591
|
+
}
|
|
592
|
+
fullyConsumed = true;
|
|
593
|
+
};
|
|
594
|
+
const readback = await verifier.rehearsal.restoreClosed(entries());
|
|
595
|
+
let rehearsalDigest;
|
|
596
|
+
let verificationFailure;
|
|
597
|
+
try {
|
|
598
|
+
if (!fullyConsumed)
|
|
599
|
+
fail('Restore rehearsal did not consume the complete backup.');
|
|
600
|
+
const actualRecordHash = plugins.crypto.createHash('sha256');
|
|
601
|
+
const actualSourceHash = plugins.crypto.createHash('sha256');
|
|
602
|
+
let actualCount = 0;
|
|
603
|
+
let actualSourceCount = 0;
|
|
604
|
+
let actualLastKey = '';
|
|
605
|
+
for await (const record of readback.records) {
|
|
606
|
+
if (!isName(record.model) || !isName(record.id) || !object(record.value)
|
|
607
|
+
|| record.value.id !== record.id)
|
|
608
|
+
fail('Rehearsal readback returned an invalid record.');
|
|
609
|
+
const key = recordKey(record.model, record.id);
|
|
610
|
+
if (key <= actualLastKey)
|
|
611
|
+
fail('Rehearsal readback order changed.');
|
|
612
|
+
actualLastKey = key;
|
|
613
|
+
actualRecordHash.update(canonicalJson(record) + '\n');
|
|
614
|
+
actualCount++;
|
|
615
|
+
}
|
|
616
|
+
for await (const source of readback.sources) {
|
|
617
|
+
if (source.kind !== 'source' || !isHash(source.sourceDigest)
|
|
618
|
+
|| hash(source.bytes) !== source.sourceDigest)
|
|
619
|
+
fail('Rehearsal source readback changed.');
|
|
620
|
+
actualSourceHash.update(canonicalJson({ ...source,
|
|
621
|
+
bytes: Buffer.from(source.bytes).toString('base64url') }) + '\n');
|
|
622
|
+
actualSourceCount++;
|
|
623
|
+
}
|
|
624
|
+
const expectedRecordDigest = expectedRecordHash.digest('hex');
|
|
625
|
+
const expectedSourceDigest = expectedSourceHash.digest('hex');
|
|
626
|
+
if (actualCount !== expectedCount || actualSourceCount !== expectedSourceCount
|
|
627
|
+
|| actualRecordHash.digest('hex') !== expectedRecordDigest
|
|
628
|
+
|| actualSourceHash.digest('hex') !== expectedSourceDigest) {
|
|
629
|
+
fail('Isolated restore readback differs from expected safe state.');
|
|
630
|
+
}
|
|
631
|
+
rehearsalDigest = hash(JSON.stringify([expectedRecordDigest, expectedSourceDigest]));
|
|
632
|
+
}
|
|
633
|
+
catch (error) {
|
|
634
|
+
verificationFailure = error;
|
|
635
|
+
}
|
|
636
|
+
let closeFailure;
|
|
637
|
+
// A matching postimage is not a receipt while the isolated owner still has a live database or child.
|
|
638
|
+
try {
|
|
639
|
+
await readback.close();
|
|
640
|
+
}
|
|
641
|
+
catch (error) {
|
|
642
|
+
closeFailure = error;
|
|
643
|
+
}
|
|
644
|
+
if (verificationFailure && closeFailure) {
|
|
645
|
+
throw new AggregateError([verificationFailure, closeFailure], 'Restore rehearsal verification and cleanup both failed.');
|
|
646
|
+
}
|
|
647
|
+
if (verificationFailure)
|
|
648
|
+
throw verificationFailure;
|
|
649
|
+
if (closeFailure)
|
|
650
|
+
throw closeFailure;
|
|
651
|
+
if (!rehearsalDigest)
|
|
652
|
+
fail('Restore rehearsal did not produce an exact postimage digest.');
|
|
653
|
+
return { backupId: manifest.backupId, manifestPath: input.manifestPath,
|
|
654
|
+
manifestDigest: input.manifestDigest, snapshotDigest: manifest.snapshotDigest, sourceEpoch: manifest.epoch,
|
|
655
|
+
sourceRevision: manifest.revision, restoredEpoch, recordCount: manifest.recordCount,
|
|
656
|
+
sources: manifest.sources, rehearsalDigest, verifiedAt: new Date().toISOString(),
|
|
657
|
+
restoreAdmission: 'closed_pending_codex_and_native_reconciliation' };
|
|
658
|
+
}
|
|
659
|
+
async restoreRecord(record, secret, restoredEpoch) {
|
|
660
|
+
const value = record.value;
|
|
661
|
+
if (!object(value))
|
|
662
|
+
fail('Invalid stored backup record.');
|
|
663
|
+
assertSnapshotRecord(record);
|
|
664
|
+
if (record.model === 'authswitch_authority_events')
|
|
665
|
+
return null;
|
|
666
|
+
if (record.model === 'authswitch_authority_usage')
|
|
667
|
+
return null;
|
|
668
|
+
if (record.model === 'authswitch_authority_meta') {
|
|
669
|
+
assertStoredAuthorityMeta(value);
|
|
670
|
+
const restored = { ...value, admission: 'closed_restored',
|
|
671
|
+
epoch: restoredEpoch, revision: 0, updateId: uuid() };
|
|
672
|
+
return { ...record, value: restored };
|
|
673
|
+
}
|
|
674
|
+
if (record.model === 'authswitch_authority_grants') {
|
|
675
|
+
assertStoredAuthorityGrant(value);
|
|
676
|
+
if ((value.ciphertext !== null) !== (secret !== null))
|
|
677
|
+
fail('Grant recovery payload is incomplete.');
|
|
678
|
+
if (value.state === 'removed')
|
|
679
|
+
return record;
|
|
680
|
+
const native = ['claude_host_native', 'opencode_native'].includes(value.purpose);
|
|
681
|
+
const restored = { ...value,
|
|
682
|
+
state: native ? 'legacy_native_pending' : 'needs_reauth',
|
|
683
|
+
owner: native ? 'legacy_native' : 'daemon', ciphertext: null, accessExpiresAt: null,
|
|
684
|
+
attemptId: null, retryAt: null, retryCount: 0,
|
|
685
|
+
problem: native ? 'native_owner' : 'exchange_uncertain',
|
|
686
|
+
grantGeneration: value.grantGeneration + 1,
|
|
687
|
+
authorizationGeneration: value.authorizationGeneration + 1,
|
|
688
|
+
revision: value.revision + 1, statusObservedAt: new Date().toISOString(), updateId: uuid() };
|
|
689
|
+
assertStoredAuthorityGrant(restored);
|
|
690
|
+
return { ...record, value: restored };
|
|
691
|
+
}
|
|
692
|
+
if (record.model === 'authswitch_authority_bindings') {
|
|
693
|
+
assertStoredAuthorityBinding(value);
|
|
694
|
+
const restored = { ...value,
|
|
695
|
+
capabilityHash: hash(plugins.crypto.randomBytes(32)), revision: value.revision + 1,
|
|
696
|
+
updateId: uuid() };
|
|
697
|
+
return { ...record, value: restored };
|
|
698
|
+
}
|
|
699
|
+
if (record.model === 'authswitch_authority_enrollments') {
|
|
700
|
+
assertStoredAuthorityEnrollment(value);
|
|
701
|
+
if (secret === null)
|
|
702
|
+
fail('Enrollment recovery payload is missing.');
|
|
703
|
+
const plaintext = Buffer.from(secret, 'base64url');
|
|
704
|
+
try {
|
|
705
|
+
const row = parseEnrollment(plaintext, value.id);
|
|
706
|
+
const sealed = await this.options.secrets.seal(value.id, plaintext);
|
|
707
|
+
const opened = await this.options.secrets.unseal(value.id, sealed);
|
|
708
|
+
try {
|
|
709
|
+
if (Buffer.compare(Buffer.from(opened), plaintext) !== 0)
|
|
710
|
+
fail('Destination enrollment reseal did not verify.');
|
|
711
|
+
}
|
|
712
|
+
finally {
|
|
713
|
+
opened.fill(0);
|
|
714
|
+
}
|
|
715
|
+
const restored = { ...value, ciphertext: sealed,
|
|
716
|
+
revision: value.revision + 1, updateId: uuid() };
|
|
717
|
+
assertStoredAuthorityEnrollment(restored);
|
|
718
|
+
if (authorityEnrollmentId(row) !== restored.id)
|
|
719
|
+
fail('Enrollment changed during destination reseal.');
|
|
720
|
+
return { ...record, value: restored };
|
|
721
|
+
}
|
|
722
|
+
finally {
|
|
723
|
+
plaintext.fill(0);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
if (record.model === 'authswitch_authority_codex_homes') {
|
|
727
|
+
assertStoredAuthorityCodexHome(value);
|
|
728
|
+
const restored = { ...value, activeRun: null, updateId: uuid() };
|
|
729
|
+
return { ...record, value: restored };
|
|
730
|
+
}
|
|
731
|
+
if (record.model === 'authswitch_authority_claude_homes') {
|
|
732
|
+
const restored = { ...value, status: 'quarantined', pendingOperationId: uuid(),
|
|
733
|
+
revision: Number(value.revision) + 1, updateId: uuid() };
|
|
734
|
+
assertStoredAuthorityClaudeHome(restored);
|
|
735
|
+
return { ...record, value: restored };
|
|
736
|
+
}
|
|
737
|
+
if (record.model === 'authswitch_authority_claude_handoffs') {
|
|
738
|
+
const restored = { ...value, phase: 'quarantined',
|
|
739
|
+
problem: 'native_uncertain', sealedOutgoing: null,
|
|
740
|
+
revision: Number(value.revision) + 1, updateId: uuid() };
|
|
741
|
+
assertStoredAuthorityClaudeHandoff(restored);
|
|
742
|
+
return { ...record, value: restored };
|
|
743
|
+
}
|
|
744
|
+
if (record.model === 'authswitch_authority_handoffs') {
|
|
745
|
+
const restored = { ...value, phase: 'needs_reauth',
|
|
746
|
+
backupDigest: null, verifiedSourceDigest: null,
|
|
747
|
+
revision: Number(value.revision) + 1, updateId: uuid() };
|
|
748
|
+
assertStoredAuthorityHandoff(restored);
|
|
749
|
+
return { ...record, value: restored };
|
|
750
|
+
}
|
|
751
|
+
if (record.model === 'authswitch_authority_migration_ledger') {
|
|
752
|
+
const restored = { ...value, status: 'prepared', backupDigest: null,
|
|
753
|
+
revision: Number(value.revision) + 1, updateId: uuid() };
|
|
754
|
+
assertStoredAuthorityMigrationLedger(restored);
|
|
755
|
+
return { ...record, value: restored };
|
|
756
|
+
}
|
|
757
|
+
if (record.model === 'authswitch_authority_operations') {
|
|
758
|
+
if (secret !== null)
|
|
759
|
+
fail('Unexpected executable secret in backup operation.');
|
|
760
|
+
assertStoredAuthorityOperation(value);
|
|
761
|
+
const restored = restoreStoredAuthorityOperation(value, { restoredAt: new Date().toISOString(), updateId: uuid() });
|
|
762
|
+
return restored === value ? record : { ...record, value: restored };
|
|
763
|
+
}
|
|
764
|
+
if (secret !== null)
|
|
765
|
+
fail('Unexpected executable secret in backup record.');
|
|
766
|
+
return record;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5hdXRob3JpdHliYWNrdXAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLmF1dGhvcml0eWJhY2t1cC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEVBQ0wsNEJBQTRCLEVBQUUsa0NBQWtDLEVBQ2hFLCtCQUErQixFQUFFLDhCQUE4QixFQUFFLCtCQUErQixFQUNoRywwQkFBMEIsRUFBRSw0QkFBNEIsRUFDeEQseUJBQXlCLEVBQUUsb0NBQW9DLEVBQUUsOEJBQThCLEVBQy9GLCtCQUErQixHQUdoQyxNQUFNLDhCQUE4QixDQUFDO0FBQ3RDLE9BQU8sRUFBRSwyQkFBMkIsRUFBK0IsTUFBTSxnQ0FBZ0MsQ0FBQztBQUkxRyxNQUFNLGtCQUFrQixHQUFHLENBQUMsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQzNDLE1BQU0sdUJBQXVCLEdBQUcsRUFBRSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFDakQscUdBQXFHO0FBQ3JHLE1BQU0sY0FBYyxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFDbkMsTUFBTSxjQUFjLEdBQUcsQ0FBQyxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFDdkMsTUFBTSxJQUFJLEdBQUcsQ0FBQyxLQUEwQixFQUFVLEVBQUUsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3JILE1BQU0sSUFBSSxHQUFHLEdBQVcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUM7QUFDdkQsTUFBTSxNQUFNLEdBQUcsQ0FBQyxLQUFjLEVBQW1CLEVBQUUsQ0FBQyxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksZ0JBQWdCLENBQUMsSUFBSSxD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
|