@modelprofile.com/authswitch 6.5.0 → 8.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 +300 -6
- package/dist_ts/authority-contract.js +1 -1
- package/dist_ts/authority-runtime-contract.d.ts +13 -0
- package/dist_ts/classes.accountlist.js +4 -3
- package/dist_ts/classes.authoritybroker.d.ts +25 -5
- package/dist_ts/classes.authoritybroker.js +388 -123
- package/dist_ts/classes.authoritycli.d.ts +24 -0
- package/dist_ts/classes.authoritycli.js +675 -0
- package/dist_ts/classes.authorityclient.d.ts +19 -7
- package/dist_ts/classes.authorityclient.js +51 -14
- package/dist_ts/classes.authoritydaemon.d.ts +28 -1
- package/dist_ts/classes.authoritydaemon.js +477 -36
- package/dist_ts/classes.authoritydatabase.d.ts +155 -11
- package/dist_ts/classes.authoritydatabase.js +1037 -69
- package/dist_ts/classes.authoritymodels.d.ts +229 -23
- package/dist_ts/classes.authoritymodels.js +867 -128
- package/dist_ts/classes.authoritypreuse.d.ts +47 -0
- package/dist_ts/classes.authoritypreuse.js +277 -0
- package/dist_ts/classes.authorityregistry.d.ts +9 -0
- package/dist_ts/classes.authorityregistry.js +32 -0
- package/dist_ts/classes.authoritysecrets.d.ts +1 -1
- package/dist_ts/classes.authoritysecrets.js +2 -2
- 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 +528 -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 +130 -0
- package/dist_ts/classes.claudenative.js +708 -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 +12 -1
- package/dist_ts/classes.codexmanaged.js +75 -14
- 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 +1 -0
- package/dist_ts/index.js +7 -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 +6 -3
- package/dist_ts/plugins.js +8 -4
- package/dist_ts/ts_migration/0001_authority_meta.d.ts +13 -0
- package/dist_ts/ts_migration/0001_authority_meta.js +44 -0
- package/dist_ts/ts_migration/0002_remove_backup_records.d.ts +17 -0
- package/dist_ts/ts_migration/0002_remove_backup_records.js +48 -0
- package/dist_ts/ts_migration/index.d.ts +6 -0
- package/dist_ts/ts_migration/index.js +12 -0
- package/package.json +3 -3
- package/readme.md +177 -14
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/authority-contract.ts +262 -9
- package/ts/authority-runtime-contract.ts +14 -0
- package/ts/classes.accountlist.ts +3 -2
- package/ts/classes.authoritybroker.ts +385 -121
- package/ts/classes.authoritycli.ts +719 -0
- package/ts/classes.authorityclient.ts +75 -18
- package/ts/classes.authoritydaemon.ts +444 -36
- package/ts/classes.authoritydatabase.ts +1076 -75
- package/ts/classes.authoritymodels.ts +642 -144
- package/ts/classes.authoritypreuse.ts +296 -0
- package/ts/classes.authorityregistry.ts +47 -0
- package/ts/classes.authoritysecrets.ts +1 -1
- package/ts/classes.authorityusage.ts +527 -0
- package/ts/classes.claudeauthority.ts +537 -0
- package/ts/classes.claudecodeharness.ts +2 -1
- package/ts/classes.claudecodelocks.ts +70 -1
- package/ts/classes.claudenative.ts +785 -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 +76 -13
- 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 +6 -0
- package/ts/interfaces.harness.ts +6 -0
- package/ts/interfaces.list.ts +9 -3
- package/ts/plugins.ts +8 -3
- package/ts/ts_migration/0001_authority_meta.ts +45 -0
- package/ts/ts_migration/0002_remove_backup_records.ts +49 -0
- package/ts/ts_migration/index.ts +12 -0
package/ts/interfaces.harness.ts
CHANGED
|
@@ -73,7 +73,13 @@ export interface IHarnessCredentialDrift {
|
|
|
73
73
|
|
|
74
74
|
/** Account IDs are opaque and scoped to one harness. Credentials never cross this interface. */
|
|
75
75
|
export interface IHarnessAccount {
|
|
76
|
+
/** Opaque authswitch identifier used for harness operations. */
|
|
76
77
|
id: string;
|
|
78
|
+
/**
|
|
79
|
+
* Stable account identifier reported by the provider, scoped by this harness and `slotId`.
|
|
80
|
+
* Null means the credential carries no exact provider identity. Never infer it from `id` or `label`.
|
|
81
|
+
*/
|
|
82
|
+
providerAccountId: string | null;
|
|
77
83
|
label: string;
|
|
78
84
|
/** Accounts in different slots can be active together (for example OpenCode providers). */
|
|
79
85
|
slotId?: string;
|
package/ts/interfaces.list.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { IAccountType, IHarnessAccount, IHarnessAccountStatus, IHarnessBill
|
|
|
2
2
|
|
|
3
3
|
/** Credential-free, versioned output of list --json. Missing status fields stay omitted. */
|
|
4
4
|
export interface IAccountList {
|
|
5
|
-
schemaVersion:
|
|
5
|
+
schemaVersion: 3;
|
|
6
6
|
generatedAt: string;
|
|
7
7
|
complete: boolean;
|
|
8
8
|
harnesses: IHarnessAccountList[];
|
|
@@ -22,7 +22,7 @@ export interface IHarnessAccountList {
|
|
|
22
22
|
|
|
23
23
|
/** Credential-free, versioned output of limits --json. One entry per account and limit type. */
|
|
24
24
|
export interface IAccountLimits {
|
|
25
|
-
schemaVersion:
|
|
25
|
+
schemaVersion: 2;
|
|
26
26
|
generatedAt: string;
|
|
27
27
|
complete: boolean;
|
|
28
28
|
limits: IAccountLimitRow[];
|
|
@@ -36,6 +36,9 @@ export interface IAccountLimitRow {
|
|
|
36
36
|
provider: string;
|
|
37
37
|
/** The account's public label, which is its email wherever the provider reports one. */
|
|
38
38
|
account: string | null;
|
|
39
|
+
/** Exact provider-native account identifier; null when unavailable or this row names no account. */
|
|
40
|
+
providerAccountId: string | null;
|
|
41
|
+
/** Opaque authswitch account identifier used for harness operations. */
|
|
39
42
|
accountId: string | null;
|
|
40
43
|
slotId?: string;
|
|
41
44
|
isActive: boolean;
|
|
@@ -61,7 +64,7 @@ export interface IAccountLimitRow {
|
|
|
61
64
|
|
|
62
65
|
/** Credential-free, versioned output of active --json. One entry per active credential slot. */
|
|
63
66
|
export interface IActiveAccounts {
|
|
64
|
-
schemaVersion:
|
|
67
|
+
schemaVersion: 2;
|
|
65
68
|
generatedAt: string;
|
|
66
69
|
complete: boolean;
|
|
67
70
|
active: IActiveAccountRow[];
|
|
@@ -72,6 +75,9 @@ export interface IActiveAccountRow {
|
|
|
72
75
|
harnessId: string;
|
|
73
76
|
provider: string;
|
|
74
77
|
account: string | null;
|
|
78
|
+
/** Exact provider-native account identifier; null when unavailable or this row names no account. */
|
|
79
|
+
providerAccountId: string | null;
|
|
80
|
+
/** Opaque authswitch account identifier used for harness operations. */
|
|
75
81
|
accountId: string | null;
|
|
76
82
|
slotId?: string;
|
|
77
83
|
/** The adapter's plan name (`max`, `pro`), sanitised but not display-formatted; null when none is known or the row names no account. */
|
package/ts/plugins.ts
CHANGED
|
@@ -24,14 +24,19 @@ export type TProperLockfile = typeof properLockfile;
|
|
|
24
24
|
*/
|
|
25
25
|
export const loadProperLockfile = (): Promise<TProperLockfile> => import('proper-lockfile');
|
|
26
26
|
|
|
27
|
+
// @lossless.org modules
|
|
28
|
+
/** Account document models, sessions and exact persistence. */
|
|
29
|
+
import * as nosqldb from '@lossless.org/client/nosqldb';
|
|
30
|
+
/** The embedded engine that hosts the per-user account database behind a private Unix socket. */
|
|
31
|
+
import * as nosqldbEngine from '@lossless.org/nosqldb';
|
|
32
|
+
export { nosqldb, nosqldbEngine };
|
|
33
|
+
|
|
27
34
|
// @push.rocks modules
|
|
28
35
|
import * as smartconsole from '@push.rocks/smartconsole';
|
|
29
|
-
import * as smartdata from '@push.rocks/smartdata';
|
|
30
|
-
import * as smartdb from '@push.rocks/smartdb';
|
|
31
36
|
import * as smartsecret from '@push.rocks/smartsecret';
|
|
32
37
|
import * as smartdaemon from '@push.rocks/smartdaemon';
|
|
33
38
|
import * as typedrequest from '@api.global/typedrequest';
|
|
34
|
-
export { smartconsole,
|
|
39
|
+
export { smartconsole, smartsecret, smartdaemon, typedrequest };
|
|
35
40
|
|
|
36
41
|
// @modelprofile.com modules
|
|
37
42
|
import * as flexModels from '@modelprofile.com/flexharness-models';
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
|
|
3
|
+
const reserved = new Set(['_id', '_smartdataRevision', '_createdAt', '_updatedAt']);
|
|
4
|
+
const currentKeys = ['id', 'epoch', 'revision', 'updateId'];
|
|
5
|
+
const uuid = (value: unknown): boolean => typeof value === 'string' && /^[a-f0-9-]{36}$/.test(value);
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Brings the metadata document of every published release to the current shape, under the exclusive
|
|
9
|
+
* LocalNoSqlDb root owner. 6.4/6.5 wrote exactly the current shape. 7.0.0 added `schemaVersion: 2` and an
|
|
10
|
+
* `admission` marker; both are removed in one compare-and-set, and an unreleased build that had already
|
|
11
|
+
* dropped `schemaVersion` loses the marker the same way. A store whose marker is not `open` was closed by a
|
|
12
|
+
* restore and is refused, never opened. Every other document is refused as unknown.
|
|
13
|
+
*
|
|
14
|
+
* The stored shape is the only record of completion: no ledger of applied module ids exists. That is what
|
|
15
|
+
* makes rewriting this published module in place sound, and it holds only while every accepted shape maps to
|
|
16
|
+
* the current one in at most one atomic write and the current shape maps to itself.
|
|
17
|
+
*/
|
|
18
|
+
export const migrateAuthorityMeta = async (db: plugins.nosqldb.SmartdataDb): Promise<void> => {
|
|
19
|
+
const collection = db.mongoDb.collection('authswitch_authority_meta');
|
|
20
|
+
const stored = await collection.findOne({ id: 'authswitch-authority' });
|
|
21
|
+
if (!stored) throw new Error('Existing authswitch authority database has no metadata.');
|
|
22
|
+
const body = Object.fromEntries(Object.entries(stored).filter(([key]) => !reserved.has(key)));
|
|
23
|
+
const hasSchemaVersion = Object.hasOwn(body, 'schemaVersion');
|
|
24
|
+
const hasAdmission = Object.hasOwn(body, 'admission');
|
|
25
|
+
if (Object.keys(body).length !== currentKeys.length + Number(hasSchemaVersion) + Number(hasAdmission)
|
|
26
|
+
|| !currentKeys.every(key => Object.hasOwn(body, key))
|
|
27
|
+
|| (hasSchemaVersion && (!hasAdmission || body.schemaVersion !== 2))
|
|
28
|
+
|| (hasAdmission && body.admission !== 'open' && body.admission !== 'closed_restored')
|
|
29
|
+
|| body.id !== 'authswitch-authority' || !uuid(body.epoch) || !uuid(body.updateId)
|
|
30
|
+
|| !Number.isSafeInteger(body.revision) || Number(body.revision) < 0) {
|
|
31
|
+
throw new Error('Existing authswitch authority metadata has an unknown schema.');
|
|
32
|
+
}
|
|
33
|
+
if (!hasAdmission) return;
|
|
34
|
+
if (body.admission !== 'open') {
|
|
35
|
+
throw new Error('Authswitch authority store was closed by a restore and cannot be opened; '
|
|
36
|
+
+ 'set the store aside and log in to each account again.');
|
|
37
|
+
}
|
|
38
|
+
const result = await collection.updateOne(
|
|
39
|
+
{ _id: stored._id, id: 'authswitch-authority', admission: 'open',
|
|
40
|
+
schemaVersion: hasSchemaVersion ? 2 : { $exists: false } },
|
|
41
|
+
{ $unset: hasSchemaVersion ? { schemaVersion: '', admission: '' } : { admission: '' } });
|
|
42
|
+
if (result.matchedCount !== 1 || result.modifiedCount !== 1) {
|
|
43
|
+
throw new Error('Authswitch authority metadata migration did not commit exactly once.');
|
|
44
|
+
}
|
|
45
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
|
|
3
|
+
const digestCollections = ['authswitch_authority_handoffs', 'authswitch_authority_migration_ledger'];
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Removes what the retired backup and restore system left in the store, under the exclusive LocalNoSqlDb root
|
|
7
|
+
* owner. 6.4.0 to 7.0.0 stored a `backupDigest` on every native handoff and migration ledger row; no release
|
|
8
|
+
* ever wrote a non-null one, so a null digest is unset and a non-null one refuses the store. Only a 7.0.0
|
|
9
|
+
* restore could mark a preuse receipt `restored_history_uncertain`, and a restore never targeted a real store, so
|
|
10
|
+
* that receipt refuses the store as well. A verified or complete ledger row must name its imported account and
|
|
11
|
+
* grant; one that does not was never written by this package and is refused. Every refusal is decided before the
|
|
12
|
+
* first write, so a refused store is left exactly as it was.
|
|
13
|
+
*
|
|
14
|
+
* The stored shape is the only record of completion: no ledger of applied module ids exists. Each row is
|
|
15
|
+
* rewritten by its own compare-and-set, so an interrupted run leaves rows this module already recognises and the
|
|
16
|
+
* next start finishes them. Once migrated, a start costs one unindexed pass over the operation receipts, of the
|
|
17
|
+
* same order as the state reconciliation every start already performs, and passes over two collections that
|
|
18
|
+
* hold one row per imported source.
|
|
19
|
+
*/
|
|
20
|
+
export const removeAuthorityBackupRecords = async (db: plugins.nosqldb.SmartdataDb): Promise<void> => {
|
|
21
|
+
const operations = db.mongoDb.collection('authswitch_authority_operations');
|
|
22
|
+
if (await operations.findOne({ problem: 'restored_history_uncertain' })) {
|
|
23
|
+
throw new Error('Authswitch authority store holds a receipt written by a restore and cannot be opened; '
|
|
24
|
+
+ 'set the store aside and log in to each account again.');
|
|
25
|
+
}
|
|
26
|
+
const ledger = db.mongoDb.collection('authswitch_authority_migration_ledger');
|
|
27
|
+
if (await ledger.findOne({ status: { $in: ['verified', 'complete'] }, $or: [{ accountId: null }, { grantId: null }] })) {
|
|
28
|
+
throw new Error('Authswitch authority store holds a verified migration without its imported account and grant.');
|
|
29
|
+
}
|
|
30
|
+
const carriers = [];
|
|
31
|
+
for (const name of digestCollections) {
|
|
32
|
+
const collection = db.mongoDb.collection(name);
|
|
33
|
+
if (!await collection.findOne({ backupDigest: { $exists: true } })) continue;
|
|
34
|
+
if (await collection.findOne({ backupDigest: { $exists: true, $ne: null } })) {
|
|
35
|
+
throw new Error('Authswitch authority store holds backup proof no release could have recorded.');
|
|
36
|
+
}
|
|
37
|
+
carriers.push(collection);
|
|
38
|
+
}
|
|
39
|
+
for (const collection of carriers) {
|
|
40
|
+
const carrier = { backupDigest: { $exists: true } };
|
|
41
|
+
for (let stored = await collection.findOne(carrier); stored; stored = await collection.findOne(carrier)) {
|
|
42
|
+
const result = await collection.updateOne({ _id: stored._id, backupDigest: null },
|
|
43
|
+
{ $unset: { backupDigest: '' } });
|
|
44
|
+
if (result.matchedCount !== 1 || result.modifiedCount !== 1) {
|
|
45
|
+
throw new Error('Authswitch authority backup record removal did not commit exactly once.');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import { migrateAuthorityMeta } from './0001_authority_meta.js';
|
|
3
|
+
import { removeAuthorityBackupRecords } from './0002_remove_backup_records.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Runs on every start of an existing store, in this fixed order. Each module recognises the published shapes it
|
|
7
|
+
* upgrades and leaves the current shape untouched, so the stored document itself records completion.
|
|
8
|
+
*/
|
|
9
|
+
export const runAuthorityMigrations = async (db: plugins.nosqldb.SmartdataDb): Promise<void> => {
|
|
10
|
+
await migrateAuthorityMeta(db);
|
|
11
|
+
await removeAuthorityBackupRecords(db);
|
|
12
|
+
};
|