@modelprofile.com/authswitch 8.1.0 → 9.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 +73 -0
- package/dist_ts/authority-contract.js +55 -2
- package/dist_ts/authority-import-contract.d.ts +8 -4
- package/dist_ts/authority-import-contract.js +12 -13
- package/dist_ts/authority-paths.d.ts +37 -0
- package/dist_ts/authority-paths.js +46 -0
- package/dist_ts/authority-runtime-contract.d.ts +11 -1
- package/dist_ts/classes.authoritybroker.d.ts +9 -0
- package/dist_ts/classes.authoritybroker.js +72 -11
- package/dist_ts/classes.authorityclient.d.ts +17 -11
- package/dist_ts/classes.authorityclient.js +47 -22
- package/dist_ts/classes.authoritydaemon.d.ts +22 -3
- package/dist_ts/classes.authoritydaemon.js +106 -59
- package/dist_ts/classes.authoritydatabase.d.ts +9 -1
- package/dist_ts/classes.authoritydatabase.js +39 -13
- package/dist_ts/classes.authorityimport.d.ts +33 -6
- package/dist_ts/classes.authorityimport.js +102 -25
- package/dist_ts/classes.authoritymodels.d.ts +4 -1
- package/dist_ts/classes.authoritymodels.js +15 -3
- package/dist_ts/classes.authoritypreuse.js +8 -3
- package/dist_ts/classes.authorityservice.d.ts +20 -11
- package/dist_ts/classes.authorityservice.js +37 -23
- package/dist_ts/classes.claudeauthority.js +19 -11
- package/dist_ts/classes.claudenative.d.ts +63 -3
- package/dist_ts/classes.claudenative.js +68 -8
- package/dist_ts/classes.cli.d.ts +10 -2
- package/dist_ts/classes.cli.js +12 -4
- package/dist_ts/classes.codexmanaged.d.ts +8 -0
- package/dist_ts/classes.codexmanaged.js +19 -12
- package/dist_ts/classes.legacyfence.d.ts +53 -0
- package/dist_ts/classes.legacyfence.js +189 -0
- package/dist_ts/classes.operations.d.ts +15 -3
- package/dist_ts/classes.operations.js +22 -4
- package/dist_ts/classes.service.d.ts +21 -2
- package/dist_ts/classes.service.js +35 -8
- package/dist_ts/classes.tui.d.ts +2 -1
- package/dist_ts/classes.tui.js +3 -2
- package/dist_ts/ts_migration/0003_claude_handoff_proof.d.ts +13 -0
- package/dist_ts/ts_migration/0003_claude_handoff_proof.js +20 -0
- package/dist_ts/ts_migration/index.js +3 -1
- package/dist_ts/ts_migration/legacysources/authswitchstores.js +5 -2
- package/dist_ts/ts_migration/legacysources/nativestores.js +15 -8
- package/dist_ts/ts_migration/legacysources/shared.d.ts +3 -2
- package/dist_ts/ts_migration/legacysources/shared.js +3 -5
- package/package.json +11 -7
- package/readme.md +188 -13
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/authority-contract.ts +125 -0
- package/ts/authority-import-contract.ts +12 -11
- package/ts/authority-paths.ts +69 -0
- package/ts/authority-runtime-contract.ts +11 -1
- package/ts/classes.authoritybroker.ts +70 -11
- package/ts/classes.authorityclient.ts +59 -21
- package/ts/classes.authoritydaemon.ts +116 -60
- package/ts/classes.authoritydatabase.ts +39 -12
- package/ts/classes.authorityimport.ts +131 -26
- package/ts/classes.authoritymodels.ts +11 -2
- package/ts/classes.authoritypreuse.ts +7 -1
- package/ts/classes.authorityservice.ts +42 -30
- package/ts/classes.claudeauthority.ts +22 -10
- package/ts/classes.claudenative.ts +104 -10
- package/ts/classes.cli.ts +14 -3
- package/ts/classes.codexmanaged.ts +18 -7
- package/ts/classes.legacyfence.ts +219 -0
- package/ts/classes.operations.ts +22 -3
- package/ts/classes.service.ts +45 -8
- package/ts/classes.tui.ts +3 -1
- package/ts/ts_migration/0003_claude_handoff_proof.ts +19 -0
- package/ts/ts_migration/index.ts +2 -0
- package/ts/ts_migration/legacysources/authswitchstores.ts +4 -1
- package/ts/ts_migration/legacysources/nativestores.ts +15 -7
- package/ts/ts_migration/legacysources/shared.ts +4 -6
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Gives every Claude native handoff journalled before 8.2.0 its `proofFailure` field.
|
|
5
|
+
*
|
|
6
|
+
* The handoff record is exact-persistence: a document with a key the shape does not declare, or without one
|
|
7
|
+
* it does, is refused rather than read loosely. A published release therefore cannot gain a field by
|
|
8
|
+
* declaring it -- the rows that already exist have to carry it too, and this is where that happens.
|
|
9
|
+
*
|
|
10
|
+
* Only the absence is filled, with `null`: no release before this one could say which condition of the
|
|
11
|
+
* native-login proof failed, so there is nothing to infer and nothing to overwrite. A row that already has
|
|
12
|
+
* the field is left exactly as it is, which is what makes an interrupted run safe to repeat.
|
|
13
|
+
*/
|
|
14
|
+
export const addClaudeHandoffProofFailure = async (db: plugins.nosqldb.SmartdataDb): Promise<void> => {
|
|
15
|
+
const handoffs = db.mongoDb.collection('authswitch_authority_claude_handoffs');
|
|
16
|
+
const missing = { proofFailure: { $exists: false } };
|
|
17
|
+
if (!await handoffs.findOne(missing)) return;
|
|
18
|
+
await handoffs.updateMany(missing, { $set: { proofFailure: null } });
|
|
19
|
+
};
|
package/ts/ts_migration/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as plugins from '../plugins.js';
|
|
2
2
|
import { migrateAuthorityMeta } from './0001_authority_meta.js';
|
|
3
3
|
import { removeAuthorityBackupRecords } from './0002_remove_backup_records.js';
|
|
4
|
+
import { addClaudeHandoffProofFailure } from './0003_claude_handoff_proof.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Runs on every start of an existing store, in this fixed order. Each module recognises the published shapes it
|
|
@@ -9,4 +10,5 @@ import { removeAuthorityBackupRecords } from './0002_remove_backup_records.js';
|
|
|
9
10
|
export const runAuthorityMigrations = async (db: plugins.nosqldb.SmartdataDb): Promise<void> => {
|
|
10
11
|
await migrateAuthorityMeta(db);
|
|
11
12
|
await removeAuthorityBackupRecords(db);
|
|
13
|
+
await addClaudeHandoffProofFailure(db);
|
|
12
14
|
};
|
|
@@ -175,7 +175,10 @@ export const readAuthSwitchStores = (locations: ILegacySourceLocations): ILegacy
|
|
|
175
175
|
try { entries = plugins.fs.readdirSync(locations.authSwitchHome, { withFileTypes: true }); }
|
|
176
176
|
catch (error) {
|
|
177
177
|
if ((error as NodeJS.ErrnoException).code === 'ENOENT') return { sources, problems };
|
|
178
|
-
|
|
178
|
+
// The store is named by what it is, never by where it is: this report goes to a CLI and to a backend,
|
|
179
|
+
// and the location of a credential store is not something either of them may be told. Everything
|
|
180
|
+
// below names an entry inside the store instead, which is what the owner needs to find it.
|
|
181
|
+
return { sources, problems: ['the authswitch store could not be listed'] };
|
|
179
182
|
}
|
|
180
183
|
for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
|
|
181
184
|
const path = plugins.path.join(locations.authSwitchHome, entry.name);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as plugins from '../../plugins.js';
|
|
2
2
|
import { CodexHome } from '../../classes.codexhome.js';
|
|
3
|
+
import { claudeNativeHomeId } from '../../classes.claudenative.js';
|
|
3
4
|
import { accessProofAvailable, accessTokenExpiry, claudeSourceIdentity, EXPIRED_ACCESS_PROBLEM, legacyHash,
|
|
4
5
|
legacySourceDigest, legacySourceId, openAiSourceIdentity, openCodeOpenAiIdentity, parseLegacyJson,
|
|
5
6
|
readLegacyFile, type ILegacySourceFile, type ILegacySourceLocations, type ILegacySourceRecord,
|
|
@@ -48,9 +49,9 @@ const countCodexEnrollments = (codexHome: CodexHome): { count: number | null; pr
|
|
|
48
49
|
} finally { database?.close(); }
|
|
49
50
|
};
|
|
50
51
|
|
|
51
|
-
|
|
52
|
+
/** `sourcePathHash` is passed in, because a Claude home's id belongs to the module that owns that home. */
|
|
53
|
+
const nativeRecord = (sourceKind: TAuthSwitchImportSourceKind, path: string, sourcePathHash: string,
|
|
52
54
|
files: readonly ILegacySourceFile[], problems: string[]): ILegacySourceRecord => {
|
|
53
|
-
const sourcePathHash = legacyHash(path);
|
|
54
55
|
return {
|
|
55
56
|
id: legacySourceId(sourceKind, sourcePathHash),
|
|
56
57
|
sourceKind,
|
|
@@ -86,7 +87,7 @@ const readCodexNative = (locations: ILegacySourceLocations, now: number): ILegac
|
|
|
86
87
|
if (read.problem === null && read.file === null) return null;
|
|
87
88
|
const files = read.file ? [read.file] : [];
|
|
88
89
|
const problems = read.problem ? [read.problem] : [];
|
|
89
|
-
const record = nativeRecord('codex_native', path, files, problems);
|
|
90
|
+
const record = nativeRecord('codex_native', path, legacyHash(path), files, problems);
|
|
90
91
|
const enrollments = countCodexEnrollments(new CodexHome(locations.codexHome));
|
|
91
92
|
record.enrollmentCount = enrollments.count;
|
|
92
93
|
if (enrollments.problem) problems.push(enrollments.problem);
|
|
@@ -114,12 +115,19 @@ const readCodexNative = (locations: ILegacySourceLocations, now: number): ILegac
|
|
|
114
115
|
};
|
|
115
116
|
|
|
116
117
|
const readClaudeNative = (locations: ILegacySourceLocations, now: number): ILegacySourceRecord | null => {
|
|
117
|
-
|
|
118
|
-
|
|
118
|
+
if (locations.claudeHome.kind === 'unusable') {
|
|
119
|
+
// Reported, never skipped and never read from a guessed location: the owner sees the defect and fixes it.
|
|
120
|
+
const { declaredCredentialFile, problem } = locations.claudeHome.defect;
|
|
121
|
+
return nativeRecord('claude_native', declaredCredentialFile,
|
|
122
|
+
claudeNativeHomeId(declaredCredentialFile), [], [problem]);
|
|
123
|
+
}
|
|
124
|
+
const { credentialFile, configFile, homeId } = locations.claudeHome.home;
|
|
125
|
+
const credentials = readLegacyFile(credentialFile, '.credentials.json');
|
|
126
|
+
const config = readLegacyFile(configFile, '.claude.json');
|
|
119
127
|
if (credentials.problem === null && credentials.file === null) return null;
|
|
120
128
|
const files = [credentials.file, config.file].filter((file): file is ILegacySourceFile => file !== null);
|
|
121
129
|
const problems = [credentials.problem, config.problem].filter((problem): problem is string => problem !== null);
|
|
122
|
-
const record = nativeRecord('claude_native',
|
|
130
|
+
const record = nativeRecord('claude_native', credentialFile, homeId, files, problems);
|
|
123
131
|
if (!credentials.file) return record;
|
|
124
132
|
const credentialData = parseLegacyJson(credentials.file.raw);
|
|
125
133
|
const configData = config.file === null ? null : parseLegacyJson(config.file.raw);
|
|
@@ -157,7 +165,7 @@ const readOpenCodeNative = (locations: ILegacySourceLocations, now: number): ILe
|
|
|
157
165
|
if (!value || typeof value !== 'object' || Array.isArray(value)) continue;
|
|
158
166
|
const entry = value as Record<string, unknown>;
|
|
159
167
|
const path = `${locations.openCodeAuthFile}#${provider}`;
|
|
160
|
-
const record = nativeRecord('opencode_native', path,
|
|
168
|
+
const record = nativeRecord('opencode_native', path, legacyHash(path),
|
|
161
169
|
[{ name: provider, raw: JSON.stringify(entry) }], []);
|
|
162
170
|
record.label = provider;
|
|
163
171
|
if (entry.type !== 'oauth') {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as plugins from '../../plugins.js';
|
|
2
2
|
import { readCredentialRaw } from '../../classes.credentialstore.js';
|
|
3
|
+
import { resolveClaudeNativeHome, type TClaudeNativeHomeResolution } from '../../classes.claudenative.js';
|
|
3
4
|
import type { TAuthSwitchImportProof, TAuthSwitchImportSourceKind,
|
|
4
5
|
TAuthSwitchImportTreatment } from '../../authority-import-contract.js';
|
|
5
6
|
|
|
@@ -50,21 +51,18 @@ export interface ILegacySourceReport {
|
|
|
50
51
|
export interface ILegacySourceLocations {
|
|
51
52
|
authSwitchHome: string;
|
|
52
53
|
codexHome: string;
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
/** Claude's own paths come from the module that owns them, so the daemon and this reader cannot drift. */
|
|
55
|
+
claudeHome: TClaudeNativeHomeResolution;
|
|
55
56
|
openCodeAuthFile: string;
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
export const resolveLegacySourceLocations = (env: NodeJS.ProcessEnv,
|
|
59
60
|
homeDirectory: string): ILegacySourceLocations => {
|
|
60
|
-
const claudeConfigDirectory = env.CLAUDE_CONFIG_DIR || plugins.path.join(homeDirectory, '.claude');
|
|
61
61
|
const dataHome = env.XDG_DATA_HOME || plugins.path.join(homeDirectory, '.local', 'share');
|
|
62
62
|
return {
|
|
63
63
|
authSwitchHome: env.AUTHSWITCH_HOME || plugins.path.join(homeDirectory, '.authswitch'),
|
|
64
64
|
codexHome: env.CODEX_HOME || plugins.path.join(homeDirectory, '.codex'),
|
|
65
|
-
|
|
66
|
-
// Claude Code keeps its account metadata beside the home directory, not inside a custom config directory.
|
|
67
|
-
claudeConfigFile: plugins.path.join(env.CLAUDE_CONFIG_DIR || homeDirectory, '.claude.json'),
|
|
65
|
+
claudeHome: resolveClaudeNativeHome(env, homeDirectory),
|
|
68
66
|
openCodeAuthFile: plugins.path.join(dataHome, 'opencode', 'auth.json'),
|
|
69
67
|
};
|
|
70
68
|
};
|