@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/readme.md
CHANGED
|
@@ -28,27 +28,53 @@ Node.js 24 or newer is required.
|
|
|
28
28
|
|
|
29
29
|
The package also exports a typed client for a per-user authswitch authority daemon. Its
|
|
30
30
|
SmartData registry stores account identity separately from sealed refresh grants, runtime
|
|
31
|
-
bindings, Codex enrollment records, and native-handoff and migration journals. A daemon
|
|
31
|
+
bindings, durable device-operation receipts, Codex enrollment records, and native-handoff and migration journals. A daemon
|
|
32
32
|
owns OpenAI device login, targeted reauthentication, and proactive refresh for grants
|
|
33
|
-
added through this API. Management snapshots
|
|
33
|
+
added through this API. Management snapshots expose separate account and login rows,
|
|
34
|
+
including each login's purpose, owner, health, problem and available actions; neither
|
|
35
|
+
snapshots nor events contain credentials.
|
|
34
36
|
|
|
35
37
|
```ts
|
|
38
|
+
import { randomUUID } from 'node:crypto';
|
|
36
39
|
import { AuthSwitchClient } from '@modelprofile.com/authswitch/authority-client';
|
|
37
40
|
import { resolveAuthSwitchAuthorityPaths } from '@modelprofile.com/authswitch';
|
|
38
41
|
|
|
39
42
|
const paths = resolveAuthSwitchAuthorityPaths();
|
|
40
43
|
const client = new AuthSwitchClient(paths.authoritySocketPath, paths.runtimeSocketPath);
|
|
41
44
|
const snapshot = await client.snapshotAll();
|
|
42
|
-
const
|
|
45
|
+
const operationId = randomUUID();
|
|
46
|
+
const operation = await client.beginAddOpenAi(operationId);
|
|
47
|
+
// Keep operation.id to discover its final result after navigation or reconnect.
|
|
48
|
+
const receipt = await client.getOperation(operation.id);
|
|
43
49
|
```
|
|
44
50
|
|
|
45
51
|
Browser code can import the credential-free DTOs from
|
|
46
52
|
`@modelprofile.com/authswitch/authority-contract`. A backend binds an account to a
|
|
47
|
-
runtime incarnation
|
|
53
|
+
runtime incarnation by exact account ID, login ID and purpose, and keeps the returned
|
|
54
|
+
capability private. Targeted reauthentication likewise requires the exact login; an
|
|
55
|
+
account's presentation default never selects a grant for either action. Completed and
|
|
56
|
+
interrupted operations remain discoverable through `getOperation()` and paged
|
|
57
|
+
`listOperations()`. A completed receipt and its account/grant change commit together, so
|
|
58
|
+
the receipt resolves a lost response or an event that arrives first. Add and reauthentication
|
|
59
|
+
callers supply one UUID for the logical start and reuse it after a lost response. Replaying that
|
|
60
|
+
UUID returns the same matching receipt without starting another provider login; using it for a
|
|
61
|
+
different target is rejected. Cancelling a durable `starting` receipt prevents a late provider
|
|
62
|
+
handle from promoting or overwriting it. Aborting a client request only detaches that request and
|
|
63
|
+
does not cancel the daemon-owned login. The runtime-only socket
|
|
48
64
|
resolves that binding to a current access token; its directory can be mounted into a
|
|
49
65
|
container without exposing the management socket. A provider that rejects a specific
|
|
50
66
|
access-token generation can request a newer one through `rejectedGrantGeneration`; the
|
|
51
67
|
authority coalesces concurrent rejection callbacks and never replays an uncertain refresh.
|
|
68
|
+
After an external Flex or OpenCode runtime has fenced new work and drained its pending access
|
|
69
|
+
resolutions and provider requests, it can release its exact binding capability through the
|
|
70
|
+
runtime socket. Every bind receives a fresh random capability, so a stale release cannot fence
|
|
71
|
+
or delete a successor even if the caller reused an incarnation label. Release waits for admitted
|
|
72
|
+
server-side resolution handlers, but handler completion does not prove response delivery and
|
|
73
|
+
cannot retract an access token already received or in use; the runtime owner therefore owns that
|
|
74
|
+
drain. Generic release cannot revoke a managed Codex binding, whose daemon-owned stop still closes
|
|
75
|
+
the runtime and clears its durable run before internal revocation. Binding release never transfers
|
|
76
|
+
or changes ownership of the account grant. External-binding recovery after an owner crash remains
|
|
77
|
+
a prerequisite for the full account-mutation cutover.
|
|
52
78
|
|
|
53
79
|
`AuthSwitchClient.subscribe(onSnapshot, onEvent, signal, { onStatus })` reports `current`
|
|
54
80
|
after a fresh snapshot or verified heartbeat, `unavailable` on disconnect or resync, and
|
|
@@ -57,6 +83,111 @@ Every change-event batch supplies a fresh snapshot before `onEvent`, so a consum
|
|
|
57
83
|
not need to reconstruct account state from events. `lastVerifiedAt` records the last
|
|
58
84
|
successful daemon response, including an empty heartbeat.
|
|
59
85
|
|
|
86
|
+
`AuthSwitchClient.doctorPage()` reads credential-free diagnostic evidence without unsealing
|
|
87
|
+
a grant, refreshing a token or contacting a provider. Each bounded page separately stamps
|
|
88
|
+
the database observation, daemon state and managed-Codex process observation. Stored account
|
|
89
|
+
and login rows explicitly report `liveCheck: not_checked`; a ready daemon therefore does not
|
|
90
|
+
claim that a stored grant or provider is healthy. Native homes and journals omit paths,
|
|
91
|
+
digests and sealed values, while managed Codex reports durable, in-memory and observed-process
|
|
92
|
+
state independently with fixed problem categories. Continue each independent cursor to inspect
|
|
93
|
+
the complete inventory. Pages are later observations rather than one atomic global snapshot,
|
|
94
|
+
and the authority metadata revision is not a change clock for every native-home record. If the
|
|
95
|
+
management socket is unavailable, an offline caller must leave the database state unknown
|
|
96
|
+
instead of starting the database to inspect it.
|
|
97
|
+
|
|
98
|
+
The authority CLI uses that daemon surface without constructing the legacy native harness adapters:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
authswitch account list [--json]
|
|
102
|
+
authswitch account add openai [--json]
|
|
103
|
+
authswitch account reauth <account-id> <login-id> [--json]
|
|
104
|
+
authswitch account operation get <operation-id> [--json]
|
|
105
|
+
authswitch account operation cancel <operation-id> [--json]
|
|
106
|
+
authswitch account operation resume <operation-id> [--json]
|
|
107
|
+
authswitch account preuse <account-id> <login-id> [--prompt <text>] [--model <id>] [--json]
|
|
108
|
+
authswitch account preuse --all [--prompt <text>] [--model <id>] [--json]
|
|
109
|
+
authswitch account preuse operation get <operation-id> [--json]
|
|
110
|
+
authswitch account preuse operation cancel <operation-id> [--json]
|
|
111
|
+
authswitch account preuse operation resume <operation-id> [--json]
|
|
112
|
+
authswitch authority doctor [--json]
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
`account list --json` prints the complete, consistent credential-free authority snapshot.
|
|
116
|
+
Its human form labels login health as stored state and does not imply a live provider check.
|
|
117
|
+
`account add openai` starts one standalone OpenAI device login. `account reauth` starts one
|
|
118
|
+
device login for the exact account and managed login IDs; it never chooses a presentation
|
|
119
|
+
default. Both commands print the durable operation ID, verification URL, user code and changed
|
|
120
|
+
receipts until completion. `account operation resume` polls only the supplied durable ID, while
|
|
121
|
+
`get` performs one read and `cancel` performs one explicit cancellation. Ctrl-C or the local
|
|
122
|
+
15-minute deadline detaches the CLI and leaves the daemon-owned operation running. If a start
|
|
123
|
+
response is lost, the fixed diagnostic reports the caller-generated operation ID and exact resume
|
|
124
|
+
command; the CLI does not replay the start request.
|
|
125
|
+
|
|
126
|
+
`account preuse` sends one quota-consuming prompt through the exact managed OpenAI account and
|
|
127
|
+
login IDs. The default prompt is `Write 2000 words about strawberries.`; `--prompt` replaces it
|
|
128
|
+
and `--model` requests one exact model. `--all` freezes one consistent authority snapshot, walks
|
|
129
|
+
its canonical daemon-owned OpenAI managed logins in snapshot order, and starts one fresh durable
|
|
130
|
+
operation per login whose stored `canPreuse` capability is true. It does not infer readiness from
|
|
131
|
+
plan, usage, token expiry or binding capability. A login whose snapshot capability is false is
|
|
132
|
+
reported as skipped with the snapshot revision, login revision, stored health, problem and
|
|
133
|
+
observation time; no request or operation ID is created for that skip.
|
|
134
|
+
|
|
135
|
+
Preuse operations run sequentially and are never retried automatically. Every terminal receipt
|
|
136
|
+
advances an `--all` run, including `not_sent` and `outcome_unknown`, while any attempted operation
|
|
137
|
+
that does not complete makes the final exit status nonzero. Snapshot-ineligible skips alone do not
|
|
138
|
+
make an otherwise successful batch fail. Running `--all` again is a new quota-consuming run with
|
|
139
|
+
new operation IDs. Use `account preuse operation resume` to continue observing an existing receipt.
|
|
140
|
+
Only the explicit `cancel` command asks the daemon to cancel one.
|
|
141
|
+
|
|
142
|
+
For `account add`, `account reauth` and `account operation resume`, `--json` writes JSON Lines:
|
|
143
|
+
each line is one complete operation receipt, and unchanged revisions are omitted. `account
|
|
144
|
+
operation get --json` and `account operation cancel --json` each write one JSON object followed by
|
|
145
|
+
a newline. Human output includes the resume command on every unfinished receipt. These device
|
|
146
|
+
commands do not switch the active native login.
|
|
147
|
+
|
|
148
|
+
For one preuse start or resume, `--json` likewise writes each complete changed receipt as one raw
|
|
149
|
+
JSON Line; preuse get and cancel write one raw JSON object. A preuse `--all --json` stream tags each
|
|
150
|
+
line as `operation` or `skipped`. Operation lines contain the complete durable receipt. Skip lines
|
|
151
|
+
contain the exact account and login IDs plus the stored snapshot evidence described above. A lost
|
|
152
|
+
start response, transport or output failure, Ctrl-C, or the local 15-minute observation deadline
|
|
153
|
+
stops the batch before another login starts and reports the current operation ID and resume command.
|
|
154
|
+
It detaches without replaying or implicitly cancelling the daemon operation.
|
|
155
|
+
|
|
156
|
+
`authority doctor --json` incrementally writes one JSON document. Its `pages` array contains
|
|
157
|
+
every independently stamped bounded page; `observationSpan` is written only after all cursors
|
|
158
|
+
complete, and `globallyAtomic` is false. A failure during paging returns nonzero and leaves the
|
|
159
|
+
document incomplete rather than presenting partial evidence as a successful observation span.
|
|
160
|
+
The doctor command imposes no inventory cap. Account listing and doctor do not contact a provider,
|
|
161
|
+
unseal a grant, mutate authority state, start the service, open the database offline or fall back
|
|
162
|
+
to a legacy credential store.
|
|
163
|
+
If the daemon is unavailable before the first response, it fails with a fixed diagnostic on
|
|
164
|
+
stderr and leaves stdout empty. The older native-store commands documented below still coexist until the coordinated
|
|
165
|
+
major-version migration and removal; these authority routes never use them.
|
|
166
|
+
|
|
167
|
+
`AuthSwitchClient.getUsage(accountId, loginId)` reads OpenAI managed limits or a Claude
|
|
168
|
+
host login's profile and usage through the management socket. The tagged, credential-free
|
|
169
|
+
reading preserves Claude's labelled five-hour, weekly and model windows, plan provenance,
|
|
170
|
+
extra usage facts and explicit partial availability. Missing values never become zero.
|
|
171
|
+
The daemon caches one result in SmartData for a bounded current and stale period; a new
|
|
172
|
+
reading emits one account event without changing the account row revision. Concurrent
|
|
173
|
+
reads and rejected-token refresh share the existing provider and authority owners; usage
|
|
174
|
+
adds no polling timer. Native Claude reads hold the qualified vendor-home lease through
|
|
175
|
+
both status requests and publication, and revalidate the exact credential and config
|
|
176
|
+
source even when serving a cached result. Native grants are never refreshed by the daemon.
|
|
177
|
+
Pending, quarantined, setup-token-without-profile-scope and other unsupported contexts
|
|
178
|
+
return explicit unavailable status without a provider request. Production native home
|
|
179
|
+
adoption still requires the separate verified migration cutover.
|
|
180
|
+
|
|
181
|
+
`AuthSwitchClient.startPreuse()` accepts one client-generated operation UUID and one exact
|
|
182
|
+
OpenAI account/login/purpose. The daemon resolves an access-only grant, optionally reads the
|
|
183
|
+
model catalog, then commits `request_may_have_started` immediately before FlexHarness sends one
|
|
184
|
+
inference with retries disabled. Reusing the UUID with the same request returns its durable receipt; changing
|
|
185
|
+
the target, prompt or requested model is rejected. A crash, cancellation or shutdown after the
|
|
186
|
+
marker remains `outcome_unknown` and is never replayed. Before-marker refusals are `not_sent`.
|
|
187
|
+
Only the request hash, selected model, timing and safe token counts are stored; the prompt,
|
|
188
|
+
generated prose and credentials are absent from persistence and management responses. Account
|
|
189
|
+
removal and targeted reauthentication refuse while that account has an active preuse request.
|
|
190
|
+
|
|
60
191
|
A trusted in-process daemon host can call `AuthSwitchAuthorityDaemon.startManagedCodex()`
|
|
61
192
|
for a bound account and workspace. It owns a private Codex 0.155.1 app-server, passes only
|
|
62
193
|
the authority's current access token through Codex's external-token login, answers its
|
|
@@ -67,10 +198,16 @@ Callers supply a private, durable `codexHomeDirectory` for Codex's own configura
|
|
|
67
198
|
conversation state. SmartData binds that home immutably to one account and scope, and the
|
|
68
199
|
daemon records its active process/socket identity before launching it. Admission refuses
|
|
69
200
|
an existing nonempty native home or a surviving app-server owner; a fresh empty home is
|
|
70
|
-
created on first use. Account removal
|
|
71
|
-
|
|
72
|
-
|
|
201
|
+
created on first use. Account removal and reauthentication refuse while an in-memory or
|
|
202
|
+
durably recorded managed Codex process for that account may still be running, including
|
|
203
|
+
after daemon restart. A recorded run is cleared only when its exact process is proven
|
|
204
|
+
gone; an uncertain launch remains blocked. Callers must explicitly stop owned processes
|
|
205
|
+
after their work finishes. Once reauthentication starts, it holds new admissions until the
|
|
206
|
+
device operation settles. Only the private socket directory is removed on close. Codex's
|
|
73
207
|
credential store remains ephemeral and does not read or write `auth.json` in that home.
|
|
208
|
+
Managed-Codex process ownership observation is qualified on Linux and reads exact argument
|
|
209
|
+
boundaries from `/proc`; on other hosts doctor reports the process observation as unknown,
|
|
210
|
+
and authority actions that require survivor proof refuse instead of guessing.
|
|
74
211
|
Codex 0.155.1 does not persist an unused thread created by `thread/start`; resume applies
|
|
75
212
|
after Codex has committed a rollout. The existing CLI has not yet been moved to this path.
|
|
76
213
|
|
|
@@ -83,6 +220,30 @@ remain vendor-owned; a container setup-token grant is a separate grant under the
|
|
|
83
220
|
account. The one-time migration and deletion of authswitch's old stores are separate
|
|
84
221
|
cutover steps.
|
|
85
222
|
|
|
223
|
+
The backend-only Claude native handoff journals an exact two-file write and transfers
|
|
224
|
+
ownership between two account grants in one SmartData transaction. An inactive Claude
|
|
225
|
+
grant is refreshed by the daemon only after a durable pre-send marker; pending, native,
|
|
226
|
+
and quarantined grants cannot enter that exchange. A native home and incoming grant
|
|
227
|
+
require a verified import receipt: a migration ledger row that binds the exact source
|
|
228
|
+
digest to one account and grant. A source counts as migrated only after such a verified
|
|
229
|
+
import. Nothing in this package writes that ledger yet, so the default daemon does not
|
|
230
|
+
configure a Claude native home or run this path against real credentials. Handoff
|
|
231
|
+
receipts are queryable after a lost response.
|
|
232
|
+
`runningEffectiveAuth: unsupported_effective_auth` means the native store changed, while
|
|
233
|
+
an already-running Claude process's effective login cannot be proven externally;
|
|
234
|
+
qualified live native-store switching still works.
|
|
235
|
+
|
|
236
|
+
The authority database admits exactly the collections of one registry and prepares each
|
|
237
|
+
at startup. Startup rejects unknown collections, unknown metadata schemas and an existing
|
|
238
|
+
store without its metadata document. Published 7.0.0 metadata is upgraded in place to the
|
|
239
|
+
shape 6.4/6.5 already wrote, while account IDs, sealed grants, enrollments and uncertain
|
|
240
|
+
states remain intact. A 7.0.0 store that a restore had marked closed is refused, not opened.
|
|
241
|
+
Startup also removes the backup digest that 6.4.0 to 7.0.0 stored on native handoff and
|
|
242
|
+
migration ledger rows, and refuses a store holding a record only the retired backup and
|
|
243
|
+
restore system could have written.
|
|
244
|
+
The store is deliberately not backed up: its refresh grants are sealed to this host's TPM,
|
|
245
|
+
so a lost store is recovered by one device re-login per account.
|
|
246
|
+
|
|
86
247
|
## Usage
|
|
87
248
|
|
|
88
249
|
Run `authswitch`, `authswitch -i`, or `authswitch --interactive` for an interactive guide. Use the arrow keys and
|
|
@@ -975,7 +1136,7 @@ arguments to these commands exit with 2.
|
|
|
975
1136
|
|
|
976
1137
|
`limits --json` emits `IAccountLimits` and `active --json` emits `IActiveAccounts`:
|
|
977
1138
|
the same rows as the tables, plus the machine-readable fields the tables condense —
|
|
978
|
-
`accountId`, `slotId`, `accountType` (`{ plan, source }` with the adapter's plan
|
|
1139
|
+
`accountId`, `providerAccountId`, `slotId`, `accountType` (`{ plan, source }` with the adapter's plan
|
|
979
1140
|
name, such as `max` or `pro`, sanitised but not display-formatted, and `source` `live`
|
|
980
1141
|
or `stored`; null when no type is known or the row names no account; both documents
|
|
981
1142
|
carry it), the limits rows' `billing` (the account's reported `hasActiveSubscription`,
|
|
@@ -986,18 +1147,20 @@ it gave none) and `headline` (true for the window the provider picks for a
|
|
|
986
1147
|
single-value summary), the ISO `savedAt` beside the human `savedAgo`, the per-row
|
|
987
1148
|
`unavailableReason` that the footnotes summarise, and `drift`, which carries the
|
|
988
1149
|
expected and current account ids, their labels, whether the current one is saved,
|
|
989
|
-
the ISO `switchedAt` of the switch that was undone, and the same sentence as `reason`.
|
|
1150
|
+
the ISO `switchedAt` of the switch that was undone, and the same sentence as `reason`. `accountId` remains the opaque
|
|
1151
|
+
authswitch identifier used for harness operations; `providerAccountId` is the exact provider-native identifier, or null
|
|
1152
|
+
when the credential reports none. Both documents carry `schemaVersion: 2`, the
|
|
990
1153
|
shared `generatedAt` snapshot every countdown is relative to, and `complete`, which
|
|
991
1154
|
is false when any account or harness could not be read.
|
|
992
1155
|
|
|
993
1156
|
The exported `IAccountList` contract contains:
|
|
994
1157
|
|
|
995
|
-
- `schemaVersion:
|
|
1158
|
+
- `schemaVersion: 3`, `generatedAt` (ISO UTC), and `complete`.
|
|
996
1159
|
- `harnesses[]`: `id`, `label`, `loginHint`, `saveUnavailableReason`, `accounts`,
|
|
997
1160
|
`credentialDrift` (slots whose file no longer holds the account the last switch
|
|
998
1161
|
wrote), and harness-level `problems` (distinguishing failed discovery from an
|
|
999
1162
|
empty list).
|
|
1000
|
-
- Each account's opaque `id`, `label`, `isActive`, verified `isStashed`, `savedAt`,
|
|
1163
|
+
- Each account's opaque `id`, exact provider-native `providerAccountId` (or null), `label`, `isActive`, verified `isStashed`, `savedAt`,
|
|
1001
1164
|
`details`, and `status` containing all labelled `facts`, `problems`, and optional
|
|
1002
1165
|
typed `summary` fields. Missing fields remain omitted, not replaced by zero;
|
|
1003
1166
|
`summary.usageWindows[]` carries `severity` and `headline` only when the provider
|
|
@@ -1009,9 +1172,9 @@ harness internals. A partial result still produces valid JSON and exits with 1;
|
|
|
1009
1172
|
successful and empty results exit with 0. `complete` describes lookup success,
|
|
1010
1173
|
not whether the provider exposes every possible metric.
|
|
1011
1174
|
|
|
1012
|
-
Version
|
|
1013
|
-
optional account `slotId` fields. Consumers
|
|
1014
|
-
accept schema version
|
|
1175
|
+
Version 3 adds `providerAccountId` without changing the opaque `id` used by mutation commands. Version 2 allowed
|
|
1176
|
+
`usageWindows[].resetAt` to be null and added optional account `slotId` fields. Consumers must
|
|
1177
|
+
accept schema version 3, preserve the two identifiers' distinct meanings and handle null provider IDs and reset timestamps. Scripts should qualify
|
|
1015
1178
|
mutation commands with `codex`, `opencode` or `claude`, since all three now register
|
|
1016
1179
|
by default. Saved Codex credentials retain their existing format.
|
|
1017
1180
|
|
package/ts/00_commitinfo_data.ts
CHANGED
package/ts/authority-contract.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { ITypedRequest } from '@api.global/typedrequest-interfaces';
|
|
2
|
+
import type { IAuthSwitchUsageSnapshot } from './classes.authorityusage.js';
|
|
3
|
+
export type { IAuthSwitchUsageSnapshot } from './classes.authorityusage.js';
|
|
2
4
|
|
|
3
5
|
/** Credential-free account management contract. Safe to import in browser code. */
|
|
4
|
-
export type
|
|
6
|
+
export type TAuthSwitchLoginPurpose = 'openai_managed' | 'claude_host_native' | 'claude_container_setup' | 'opencode_native';
|
|
7
|
+
export type TAuthSwitchLoginHealth = 'ready' | 'refreshing' | 'retry_wait' | 'needs_reauth' | 'unverified' | 'pending_handoff' | 'handoff_quarantined' | 'removed';
|
|
5
8
|
|
|
6
9
|
export interface IAuthSwitchAccount {
|
|
7
10
|
id: string;
|
|
@@ -9,14 +12,26 @@ export interface IAuthSwitchAccount {
|
|
|
9
12
|
label: string;
|
|
10
13
|
email: string | null;
|
|
11
14
|
plan: string | null;
|
|
12
|
-
|
|
15
|
+
removed: boolean;
|
|
16
|
+
revision: number;
|
|
17
|
+
statusObservedAt: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** One independently owned login. Native ownership does not imply observed health. */
|
|
21
|
+
export interface IAuthSwitchLogin {
|
|
22
|
+
id: string;
|
|
23
|
+
accountId: string;
|
|
24
|
+
providerId: string;
|
|
25
|
+
purpose: TAuthSwitchLoginPurpose;
|
|
13
26
|
owner: 'daemon' | 'claude_native' | 'legacy_native' | 'none';
|
|
27
|
+
health: TAuthSwitchLoginHealth;
|
|
28
|
+
problem: 'none' | 'provider_unavailable' | 'exchange_uncertain' | 'provider_rejected' | 'native_owner';
|
|
14
29
|
grantGeneration: number;
|
|
15
30
|
revision: number;
|
|
16
31
|
accessExpiresAt: string | null;
|
|
17
32
|
retryAt: string | null;
|
|
18
|
-
problem: 'none' | 'provider_unavailable' | 'exchange_uncertain' | 'provider_rejected' | 'native_owner';
|
|
19
33
|
statusObservedAt: string;
|
|
34
|
+
capabilities: { canReauthenticate: boolean; canBind: boolean; canPreuse: boolean };
|
|
20
35
|
}
|
|
21
36
|
|
|
22
37
|
export interface IAuthSwitchBinding {
|
|
@@ -29,16 +44,150 @@ export interface IAuthSwitchBinding {
|
|
|
29
44
|
}
|
|
30
45
|
|
|
31
46
|
export interface IAuthSwitchSnapshot {
|
|
32
|
-
schemaVersion:
|
|
47
|
+
schemaVersion: 2;
|
|
33
48
|
epoch: string;
|
|
34
49
|
revision: number;
|
|
35
50
|
generatedAt: string;
|
|
36
51
|
accounts: IAuthSwitchAccount[];
|
|
52
|
+
logins: IAuthSwitchLogin[];
|
|
37
53
|
bindings: IAuthSwitchBinding[];
|
|
38
54
|
nextAccountCursor: string | null;
|
|
55
|
+
nextLoginCursor: string | null;
|
|
39
56
|
nextBindingCursor: string | null;
|
|
40
57
|
}
|
|
41
58
|
|
|
59
|
+
/** Persisted account evidence. No provider request is made while collecting diagnostics. */
|
|
60
|
+
export interface IAuthSwitchDoctorAccountEvidence {
|
|
61
|
+
id: string;
|
|
62
|
+
providerId: string;
|
|
63
|
+
removed: boolean;
|
|
64
|
+
statusObservedAt: string;
|
|
65
|
+
evidence: 'stored';
|
|
66
|
+
liveCheck: 'not_checked';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Persisted login evidence. Stored readiness is not a live provider-health claim. */
|
|
70
|
+
export interface IAuthSwitchDoctorLoginEvidence {
|
|
71
|
+
id: string;
|
|
72
|
+
accountId: string;
|
|
73
|
+
providerId: string;
|
|
74
|
+
purpose: TAuthSwitchLoginPurpose;
|
|
75
|
+
owner: 'daemon' | 'claude_native' | 'legacy_native' | 'none';
|
|
76
|
+
state: 'ready' | 'exchange_may_have_been_sent' | 'retry_wait' | 'needs_reauth' | 'native'
|
|
77
|
+
| 'legacy_native_pending' | 'handoff_pending' | 'handoff_quarantined' | 'removed';
|
|
78
|
+
problem: 'none' | 'provider_unavailable' | 'exchange_uncertain' | 'provider_rejected' | 'native_owner';
|
|
79
|
+
grantGeneration: number;
|
|
80
|
+
authorizationGeneration: number;
|
|
81
|
+
accessExpiresAt: string | null;
|
|
82
|
+
retryAt: string | null;
|
|
83
|
+
statusObservedAt: string;
|
|
84
|
+
evidence: 'stored';
|
|
85
|
+
liveCheck: 'not_checked';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface IAuthSwitchDoctorManagedCodex {
|
|
89
|
+
homeId: string;
|
|
90
|
+
accountId: string;
|
|
91
|
+
loginId: string;
|
|
92
|
+
scopeId: string;
|
|
93
|
+
health: 'healthy' | 'degraded' | 'unknown';
|
|
94
|
+
durable: {
|
|
95
|
+
state: 'idle' | 'launch_prepared' | 'registered';
|
|
96
|
+
runId: string | null;
|
|
97
|
+
pid: number | null;
|
|
98
|
+
startedAt: string | null;
|
|
99
|
+
};
|
|
100
|
+
daemon: {
|
|
101
|
+
state: 'untracked' | 'starting' | 'ready' | 'stopping' | 'degraded';
|
|
102
|
+
assignment: 'untracked' | 'matches' | 'mismatch';
|
|
103
|
+
};
|
|
104
|
+
process: {
|
|
105
|
+
state: 'not_expected' | 'absent' | 'observed' | 'unknown';
|
|
106
|
+
identity: 'not_applicable' | 'unregistered' | 'matches' | 'mismatch' | 'unknown';
|
|
107
|
+
pid: number | null;
|
|
108
|
+
startedAt: string | null;
|
|
109
|
+
observedAt: string;
|
|
110
|
+
problem: 'none' | 'inspection_failed' | 'multiple_claimants';
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface IAuthSwitchDoctorClaudeHome {
|
|
115
|
+
id: string;
|
|
116
|
+
activeAccountId: string;
|
|
117
|
+
activeLoginId: string;
|
|
118
|
+
pendingOperationId: string | null;
|
|
119
|
+
status: 'ready' | 'quarantined';
|
|
120
|
+
revision: number;
|
|
121
|
+
createdAt: string;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface IAuthSwitchDoctorClaudeHandoff {
|
|
125
|
+
id: string;
|
|
126
|
+
homeId: string;
|
|
127
|
+
outgoingAccountId: string;
|
|
128
|
+
outgoingLoginId: string;
|
|
129
|
+
incomingAccountId: string;
|
|
130
|
+
incomingLoginId: string;
|
|
131
|
+
phase: 'reserved' | 'prepared' | 'committed' | 'aborted' | 'quarantined';
|
|
132
|
+
problem: 'none' | 'native_uncertain' | 'foreign_or_torn' | 'unsupported_effective_auth' | 'database_uncertain';
|
|
133
|
+
runningEffectiveAuth: 'no_scoped_sessions' | 'unsupported_effective_auth' | null;
|
|
134
|
+
startedAt: string;
|
|
135
|
+
updatedAt: string;
|
|
136
|
+
revision: number;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface IAuthSwitchDoctorNativeHandoff {
|
|
140
|
+
id: string;
|
|
141
|
+
accountId: string;
|
|
142
|
+
loginId: string;
|
|
143
|
+
nativeHomeId: string;
|
|
144
|
+
direction: 'to_native' | 'to_daemon';
|
|
145
|
+
phase: 'prepared' | 'source_stopped' | 'target_written' | 'verified' | 'committed' | 'needs_reauth' | 'aborted';
|
|
146
|
+
operationId: string;
|
|
147
|
+
revision: number;
|
|
148
|
+
statusObservedAt: string;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export interface IAuthSwitchDoctorMigration {
|
|
152
|
+
id: string;
|
|
153
|
+
sourceKind: 'authswitch_stash' | 'authswitch_backup' | 'agl_flex' | 'codex_native' | 'opencode_native' | 'claude_native';
|
|
154
|
+
status: 'pending_native_owner' | 'prepared' | 'verified' | 'complete' | 'quarantined';
|
|
155
|
+
accountId: string | null;
|
|
156
|
+
loginId: string | null;
|
|
157
|
+
revision: number;
|
|
158
|
+
statusObservedAt: string;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** One independently observed diagnostic page. Separate pages are not one atomic global snapshot. */
|
|
162
|
+
export interface IAuthSwitchDoctorPage {
|
|
163
|
+
observedAt: string;
|
|
164
|
+
daemon: {
|
|
165
|
+
state: 'ready' | 'closing';
|
|
166
|
+
claudeNativeAuthority: 'configured' | 'not_configured';
|
|
167
|
+
observedAt: string;
|
|
168
|
+
};
|
|
169
|
+
database: {
|
|
170
|
+
state: 'available';
|
|
171
|
+
observedAt: string;
|
|
172
|
+
epoch: string;
|
|
173
|
+
revision: number;
|
|
174
|
+
};
|
|
175
|
+
accounts: IAuthSwitchDoctorAccountEvidence[];
|
|
176
|
+
logins: IAuthSwitchDoctorLoginEvidence[];
|
|
177
|
+
managedCodex: IAuthSwitchDoctorManagedCodex[];
|
|
178
|
+
claudeHomes: IAuthSwitchDoctorClaudeHome[];
|
|
179
|
+
claudeHandoffs: IAuthSwitchDoctorClaudeHandoff[];
|
|
180
|
+
nativeHandoffs: IAuthSwitchDoctorNativeHandoff[];
|
|
181
|
+
migrations: IAuthSwitchDoctorMigration[];
|
|
182
|
+
nextAccountCursor: string | null;
|
|
183
|
+
nextLoginCursor: string | null;
|
|
184
|
+
nextCodexHomeCursor: string | null;
|
|
185
|
+
nextClaudeHomeCursor: string | null;
|
|
186
|
+
nextClaudeHandoffCursor: string | null;
|
|
187
|
+
nextNativeHandoffCursor: string | null;
|
|
188
|
+
nextMigrationCursor: string | null;
|
|
189
|
+
}
|
|
190
|
+
|
|
42
191
|
export interface IAuthSwitchAccountEvent {
|
|
43
192
|
epoch: string;
|
|
44
193
|
revision: number;
|
|
@@ -52,18 +201,97 @@ export type TAuthSwitchLoginPrompt =
|
|
|
52
201
|
|
|
53
202
|
export interface IAuthSwitchOperation {
|
|
54
203
|
id: string;
|
|
55
|
-
|
|
204
|
+
kind: 'add_openai' | 'reauth_openai';
|
|
205
|
+
purpose: 'openai_managed';
|
|
206
|
+
targetAccountId: string | null;
|
|
207
|
+
targetLoginId: string | null;
|
|
208
|
+
state: 'starting' | 'pending' | 'committing' | 'complete' | 'failed' | 'cancelled' | 'interrupted' | 'outcome_unknown';
|
|
56
209
|
prompt: TAuthSwitchLoginPrompt | null;
|
|
57
|
-
|
|
210
|
+
result: { accountId: string; loginId: string; accountRevision: number; loginGeneration: number } | null;
|
|
58
211
|
error: string | null;
|
|
212
|
+
createdAt: string;
|
|
213
|
+
updatedAt: string;
|
|
214
|
+
finishedAt: string | null;
|
|
215
|
+
revision: number;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** Credential-free receipt for one exact, never-replayed quota-consuming request. */
|
|
219
|
+
export interface IAuthSwitchPreuseOperation {
|
|
220
|
+
id: string;
|
|
221
|
+
accountId: string;
|
|
222
|
+
loginId: string;
|
|
223
|
+
purpose: 'openai_managed';
|
|
224
|
+
requestedModel: string | null;
|
|
225
|
+
model: string | null;
|
|
226
|
+
state: 'preparing' | 'request_may_have_started' | 'complete' | 'not_sent' | 'outcome_unknown';
|
|
227
|
+
result: { inputTokens: number | null; outputTokens: number | null; totalTokens: number | null } | null;
|
|
228
|
+
problem: 'none' | 'target_unavailable' | 'access_unavailable' | 'catalog_unavailable'
|
|
229
|
+
| 'account_busy' | 'cancelled' | 'authority_closing' | 'interrupted'
|
|
230
|
+
| 'request_uncertain';
|
|
231
|
+
createdAt: string;
|
|
232
|
+
updatedAt: string;
|
|
233
|
+
finishedAt: string | null;
|
|
234
|
+
revision: number;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** Credential-free native file ownership result. It makes no claim about a running session's active request. */
|
|
238
|
+
export interface IAuthSwitchClaudeNativeHandoff {
|
|
239
|
+
id: string;
|
|
240
|
+
homeId: string;
|
|
241
|
+
outgoingAccountId: string;
|
|
242
|
+
incomingAccountId: string;
|
|
243
|
+
phase: 'reserved' | 'prepared' | 'committed' | 'aborted' | 'quarantined';
|
|
244
|
+
problem: 'none' | 'native_uncertain' | 'foreign_or_torn' | 'unsupported_effective_auth' | 'database_uncertain';
|
|
245
|
+
runningEffectiveAuth: 'no_scoped_sessions' | 'unsupported_effective_auth' | null;
|
|
246
|
+
updatedAt: string;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export interface IReq_AuthSwitchSwitchClaudeNative extends ITypedRequest {
|
|
250
|
+
method: 'authswitch.authority.claude.switch';
|
|
251
|
+
request: { accountId: string; loginId: string; purpose: 'claude_host_native' };
|
|
252
|
+
response: { handoff: IAuthSwitchClaudeNativeHandoff };
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export interface IReq_AuthSwitchClaudeNativeHandoff extends ITypedRequest {
|
|
256
|
+
method: 'authswitch.authority.claude.handoff';
|
|
257
|
+
request: { operationId: string };
|
|
258
|
+
response: { handoff: IAuthSwitchClaudeNativeHandoff };
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export interface IReq_AuthSwitchClaudeNativeHandoffs extends ITypedRequest {
|
|
262
|
+
method: 'authswitch.authority.claude.handoffs';
|
|
263
|
+
request: { after?: string; limit?: number };
|
|
264
|
+
response: { handoffs: IAuthSwitchClaudeNativeHandoff[]; nextCursor: string | null };
|
|
59
265
|
}
|
|
60
266
|
|
|
61
267
|
export interface IReq_AuthSwitchSnapshot extends ITypedRequest {
|
|
62
268
|
method: 'authswitch.authority.snapshot';
|
|
63
|
-
request: { accountAfter?: string; bindingAfter?: string; limit?: number };
|
|
269
|
+
request: { accountAfter?: string; loginAfter?: string; bindingAfter?: string; limit?: number };
|
|
64
270
|
response: { snapshot: IAuthSwitchSnapshot };
|
|
65
271
|
}
|
|
66
272
|
|
|
273
|
+
export interface IReq_AuthSwitchDoctor extends ITypedRequest {
|
|
274
|
+
method: 'authswitch.authority.doctor';
|
|
275
|
+
request: {
|
|
276
|
+
accountAfter?: string;
|
|
277
|
+
loginAfter?: string;
|
|
278
|
+
codexHomeAfter?: string;
|
|
279
|
+
claudeHomeAfter?: string;
|
|
280
|
+
claudeHandoffAfter?: string;
|
|
281
|
+
nativeHandoffAfter?: string;
|
|
282
|
+
migrationAfter?: string;
|
|
283
|
+
limit?: number;
|
|
284
|
+
};
|
|
285
|
+
response: { page: IAuthSwitchDoctorPage };
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/** Management-only usage read. The DTO contains no access or refresh credential. */
|
|
289
|
+
export interface IReq_AuthSwitchUsage extends ITypedRequest {
|
|
290
|
+
method: 'authswitch.authority.usage';
|
|
291
|
+
request: { accountId: string; loginId: string; force?: boolean };
|
|
292
|
+
response: { usage: IAuthSwitchUsageSnapshot };
|
|
293
|
+
}
|
|
294
|
+
|
|
67
295
|
export interface IReq_AuthSwitchEvents extends ITypedRequest {
|
|
68
296
|
method: 'authswitch.authority.events';
|
|
69
297
|
request: { epoch: string; afterRevision: number; waitMs: number };
|
|
@@ -72,16 +300,22 @@ export interface IReq_AuthSwitchEvents extends ITypedRequest {
|
|
|
72
300
|
|
|
73
301
|
export interface IReq_AuthSwitchBeginAdd extends ITypedRequest {
|
|
74
302
|
method: 'authswitch.authority.add';
|
|
75
|
-
request: { providerId: 'openai'; flow: 'device' };
|
|
303
|
+
request: { operationId: string; providerId: 'openai'; flow: 'device' };
|
|
76
304
|
response: { operation: IAuthSwitchOperation };
|
|
77
305
|
}
|
|
78
306
|
|
|
79
307
|
export interface IReq_AuthSwitchBeginReauth extends ITypedRequest {
|
|
80
308
|
method: 'authswitch.authority.reauth';
|
|
81
|
-
request: { accountId: string; flow: 'device' };
|
|
309
|
+
request: { operationId: string; accountId: string; loginId: string; purpose: 'openai_managed'; flow: 'device' };
|
|
82
310
|
response: { operation: IAuthSwitchOperation };
|
|
83
311
|
}
|
|
84
312
|
|
|
313
|
+
export interface IReq_AuthSwitchListOperations extends ITypedRequest {
|
|
314
|
+
method: 'authswitch.authority.operations';
|
|
315
|
+
request: { after?: string; limit?: number };
|
|
316
|
+
response: { operations: IAuthSwitchOperation[]; nextCursor: string | null };
|
|
317
|
+
}
|
|
318
|
+
|
|
85
319
|
export interface IReq_AuthSwitchGetOperation extends ITypedRequest {
|
|
86
320
|
method: 'authswitch.authority.operation';
|
|
87
321
|
request: { operationId: string };
|
|
@@ -94,6 +328,25 @@ export interface IReq_AuthSwitchCancelOperation extends ITypedRequest {
|
|
|
94
328
|
response: { operation: IAuthSwitchOperation };
|
|
95
329
|
}
|
|
96
330
|
|
|
331
|
+
export interface IReq_AuthSwitchStartPreuse extends ITypedRequest {
|
|
332
|
+
method: 'authswitch.authority.preuse.start';
|
|
333
|
+
request: { operationId: string; accountId: string; loginId: string; purpose: 'openai_managed';
|
|
334
|
+
prompt: string; model?: string };
|
|
335
|
+
response: { operation: IAuthSwitchPreuseOperation };
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export interface IReq_AuthSwitchGetPreuse extends ITypedRequest {
|
|
339
|
+
method: 'authswitch.authority.preuse.operation';
|
|
340
|
+
request: { operationId: string };
|
|
341
|
+
response: { operation: IAuthSwitchPreuseOperation };
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
export interface IReq_AuthSwitchCancelPreuse extends ITypedRequest {
|
|
345
|
+
method: 'authswitch.authority.preuse.cancel';
|
|
346
|
+
request: { operationId: string };
|
|
347
|
+
response: { operation: IAuthSwitchPreuseOperation };
|
|
348
|
+
}
|
|
349
|
+
|
|
97
350
|
export interface IReq_AuthSwitchRenameAccount extends ITypedRequest {
|
|
98
351
|
method: 'authswitch.authority.rename';
|
|
99
352
|
request: { accountId: string; expectedRevision: number; label: string };
|
|
@@ -6,6 +6,8 @@ export interface IReq_AuthSwitchBindAccount extends ITypedRequest {
|
|
|
6
6
|
method: 'authswitch.authority.bind';
|
|
7
7
|
request: {
|
|
8
8
|
accountId: string;
|
|
9
|
+
loginId: string;
|
|
10
|
+
purpose: 'openai_managed';
|
|
9
11
|
runtime: IAuthSwitchBinding['runtime'];
|
|
10
12
|
scopeId: string;
|
|
11
13
|
incarnationId: string;
|
|
@@ -31,3 +33,15 @@ export interface IReq_AuthSwitchResolveAccess extends ITypedRequest {
|
|
|
31
33
|
grantGeneration: number;
|
|
32
34
|
};
|
|
33
35
|
}
|
|
36
|
+
|
|
37
|
+
/** Backend-only release for one exact external runtime capability. */
|
|
38
|
+
export interface IReq_AuthSwitchReleaseBinding extends ITypedRequest {
|
|
39
|
+
method: 'authswitch.authority.release';
|
|
40
|
+
request: {
|
|
41
|
+
bindingId: string;
|
|
42
|
+
capability: string;
|
|
43
|
+
};
|
|
44
|
+
response: {
|
|
45
|
+
state: 'released' | 'inactive';
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -29,7 +29,8 @@ export const readAccountList = async (harnessesArg: IAuthHarness[]): Promise<IAc
|
|
|
29
29
|
result.saveUnavailableReason = state.saveUnavailableReason;
|
|
30
30
|
result.credentialDrift = state.credentialDrift ?? [];
|
|
31
31
|
result.accounts = rows.map(({ account, status }) => ({
|
|
32
|
-
id: account.id,
|
|
32
|
+
id: account.id, providerAccountId: account.providerAccountId, label: account.label,
|
|
33
|
+
isActive: account.isActive, isStashed: account.isStashed,
|
|
33
34
|
savedAt: account.savedAt, details: [...account.details], ...(account.slotId === undefined ? {} : { slotId: account.slotId }),
|
|
34
35
|
status: publicStatus(status!),
|
|
35
36
|
}));
|
|
@@ -39,7 +40,7 @@ export const readAccountList = async (harnessesArg: IAuthHarness[]): Promise<IAc
|
|
|
39
40
|
harnesses.push(result);
|
|
40
41
|
}
|
|
41
42
|
return {
|
|
42
|
-
schemaVersion:
|
|
43
|
+
schemaVersion: 3, generatedAt: new Date().toISOString(),
|
|
43
44
|
complete: harnesses.every(harness => !harness.problems.length && harness.accounts.every(account => !account.status.problems.length)),
|
|
44
45
|
harnesses,
|
|
45
46
|
};
|