@cortexkit/antigravity-auth-core 2.2.1 → 3.0.1
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/README.md +24 -2
- package/dist/abort-forwarding.d.ts +3 -0
- package/dist/abort-forwarding.d.ts.map +1 -0
- package/dist/abort-forwarding.js +19 -0
- package/dist/abort-forwarding.js.map +1 -0
- package/dist/account-identity.d.ts +52 -0
- package/dist/account-identity.d.ts.map +1 -0
- package/dist/account-identity.js +66 -0
- package/dist/account-identity.js.map +1 -0
- package/dist/account-manager.d.ts +228 -43
- package/dist/account-manager.d.ts.map +1 -1
- package/dist/account-manager.js +942 -903
- package/dist/account-manager.js.map +1 -1
- package/dist/account-migration.d.ts +309 -0
- package/dist/account-migration.d.ts.map +1 -0
- package/dist/account-migration.js +2284 -0
- package/dist/account-migration.js.map +1 -0
- package/dist/account-repository-codecs.d.ts +82 -0
- package/dist/account-repository-codecs.d.ts.map +1 -0
- package/dist/account-repository-codecs.js +609 -0
- package/dist/account-repository-codecs.js.map +1 -0
- package/dist/account-repository-types.d.ts +831 -0
- package/dist/account-repository-types.d.ts.map +1 -0
- package/dist/account-repository-types.js +137 -0
- package/dist/account-repository-types.js.map +1 -0
- package/dist/account-repository.d.ts +442 -0
- package/dist/account-repository.d.ts.map +1 -0
- package/dist/account-repository.js +2253 -0
- package/dist/account-repository.js.map +1 -0
- package/dist/account-selector.d.ts +470 -0
- package/dist/account-selector.d.ts.map +1 -0
- package/dist/account-selector.js +1383 -0
- package/dist/account-selector.js.map +1 -0
- package/dist/account-storage.d.ts.map +1 -1
- package/dist/account-storage.js +5 -0
- package/dist/account-storage.js.map +1 -1
- package/dist/agy-request-metadata.d.ts.map +1 -1
- package/dist/agy-request-metadata.js +8 -21
- package/dist/agy-request-metadata.js.map +1 -1
- package/dist/agy-transport.d.ts.map +1 -1
- package/dist/agy-transport.js +21 -35
- package/dist/agy-transport.js.map +1 -1
- package/dist/antigravity-command-menu.d.ts +171 -0
- package/dist/antigravity-command-menu.d.ts.map +1 -0
- package/dist/antigravity-command-menu.js +523 -0
- package/dist/antigravity-command-menu.js.map +1 -0
- package/dist/atomic-write.d.ts +18 -1
- package/dist/atomic-write.d.ts.map +1 -1
- package/dist/atomic-write.js +15 -3
- package/dist/atomic-write.js.map +1 -1
- package/dist/common-auth-embedded/NOTICE.txt +21 -0
- package/dist/common-auth-embedded/auth-menu/accounts.d.ts +97 -0
- package/dist/common-auth-embedded/auth-menu/accounts.js +387 -0
- package/dist/common-auth-embedded/auth-menu/ansi.d.ts +26 -0
- package/dist/common-auth-embedded/auth-menu/ansi.js +98 -0
- package/dist/common-auth-embedded/auth-menu/confirm.d.ts +7 -0
- package/dist/common-auth-embedded/auth-menu/confirm.js +21 -0
- package/dist/common-auth-embedded/auth-menu/doctor.d.ts +52 -0
- package/dist/common-auth-embedded/auth-menu/doctor.js +81 -0
- package/dist/common-auth-embedded/auth-menu/index.d.ts +17 -0
- package/dist/common-auth-embedded/auth-menu/index.js +12 -0
- package/dist/common-auth-embedded/auth-menu/login.d.ts +55 -0
- package/dist/common-auth-embedded/auth-menu/login.js +83 -0
- package/dist/common-auth-embedded/auth-menu/menu.d.ts +59 -0
- package/dist/common-auth-embedded/auth-menu/menu.js +73 -0
- package/dist/common-auth-embedded/auth-menu/opencode-v1.d.ts +49 -0
- package/dist/common-auth-embedded/auth-menu/opencode-v1.js +47 -0
- package/dist/common-auth-embedded/auth-menu/select.d.ts +21 -0
- package/dist/common-auth-embedded/auth-menu/select.js +159 -0
- package/dist/common-auth-embedded/auth-menu/terminal.d.ts +43 -0
- package/dist/common-auth-embedded/auth-menu/terminal.js +19 -0
- package/dist/common-auth-embedded/claustrum/consumer.d.ts +102 -0
- package/dist/common-auth-embedded/claustrum/consumer.js +298 -0
- package/dist/common-auth-embedded/claustrum/custody.d.ts +175 -0
- package/dist/common-auth-embedded/claustrum/custody.js +354 -0
- package/dist/common-auth-embedded/claustrum/enrollment.d.ts +158 -0
- package/dist/common-auth-embedded/claustrum/enrollment.js +759 -0
- package/dist/common-auth-embedded/claustrum/errors.d.ts +16 -0
- package/dist/common-auth-embedded/claustrum/errors.js +8 -0
- package/dist/common-auth-embedded/claustrum/host-slot.d.ts +39 -0
- package/dist/common-auth-embedded/claustrum/host-slot.js +72 -0
- package/dist/common-auth-embedded/claustrum/index.d.ts +18 -0
- package/dist/common-auth-embedded/claustrum/index.js +22 -0
- package/dist/common-auth-embedded/claustrum/interlock.d.ts +27 -0
- package/dist/common-auth-embedded/claustrum/interlock.js +29 -0
- package/dist/common-auth-embedded/claustrum/roster.d.ts +208 -0
- package/dist/common-auth-embedded/claustrum/roster.js +536 -0
- package/dist/common-auth-embedded/commands/builtins.d.ts +71 -0
- package/dist/common-auth-embedded/commands/builtins.js +534 -0
- package/dist/common-auth-embedded/commands/index.d.ts +10 -0
- package/dist/common-auth-embedded/commands/index.js +5 -0
- package/dist/common-auth-embedded/commands/menu.d.ts +61 -0
- package/dist/common-auth-embedded/commands/menu.js +300 -0
- package/dist/common-auth-embedded/commands/model.d.ts +238 -0
- package/dist/common-auth-embedded/commands/model.js +16 -0
- package/dist/common-auth-embedded/commands/pi.d.ts +23 -0
- package/dist/common-auth-embedded/commands/pi.js +206 -0
- package/dist/common-auth-embedded/commands/seam.d.ts +72 -0
- package/dist/common-auth-embedded/commands/seam.js +301 -0
- package/dist/common-auth-embedded/fs/atomic-write.d.ts +20 -0
- package/dist/common-auth-embedded/fs/atomic-write.js +80 -0
- package/dist/common-auth-embedded/fs/index.d.ts +7 -0
- package/dist/common-auth-embedded/fs/index.js +6 -0
- package/dist/common-auth-embedded/fs/lock-constants.d.ts +14 -0
- package/dist/common-auth-embedded/fs/lock-constants.js +14 -0
- package/dist/common-auth-embedded/fs/refresh-file-lock.d.ts +33 -0
- package/dist/common-auth-embedded/fs/refresh-file-lock.js +501 -0
- package/dist/common-auth-embedded/fs/with-lock.d.ts +33 -0
- package/dist/common-auth-embedded/fs/with-lock.js +48 -0
- package/dist/common-auth-embedded/logger/capture-sink.d.ts +14 -0
- package/dist/common-auth-embedded/logger/capture-sink.js +13 -0
- package/dist/common-auth-embedded/logger/engine.d.ts +100 -0
- package/dist/common-auth-embedded/logger/engine.js +246 -0
- package/dist/common-auth-embedded/logger/index.d.ts +6 -0
- package/dist/common-auth-embedded/logger/index.js +3 -0
- package/dist/common-auth-embedded/logger/redact.d.ts +11 -0
- package/dist/common-auth-embedded/logger/redact.js +83 -0
- package/dist/common-auth-embedded/pi-slot/index.d.ts +3 -0
- package/dist/common-auth-embedded/pi-slot/index.js +2 -0
- package/dist/common-auth-embedded/pi-slot/lock.js +212 -0
- package/dist/common-auth-embedded/pi-slot/slot.d.ts +49 -0
- package/dist/common-auth-embedded/pi-slot/slot.js +383 -0
- package/dist/common-auth-embedded/quota/codec.d.ts +11 -0
- package/dist/common-auth-embedded/quota/codec.js +12 -0
- package/dist/common-auth-embedded/quota/format.d.ts +46 -0
- package/dist/common-auth-embedded/quota/format.js +138 -0
- package/dist/common-auth-embedded/quota/index.d.ts +10 -0
- package/dist/common-auth-embedded/quota/index.js +5 -0
- package/dist/common-auth-embedded/quota/map.d.ts +63 -0
- package/dist/common-auth-embedded/quota/map.js +105 -0
- package/dist/common-auth-embedded/quota/merge.d.ts +48 -0
- package/dist/common-auth-embedded/quota/merge.js +162 -0
- package/dist/common-auth-embedded/quota/projection.d.ts +64 -0
- package/dist/common-auth-embedded/quota/projection.js +134 -0
- package/dist/common-auth-embedded/routing/admission.d.ts +93 -0
- package/dist/common-auth-embedded/routing/admission.js +142 -0
- package/dist/common-auth-embedded/routing/index.d.ts +8 -0
- package/dist/common-auth-embedded/routing/index.js +4 -0
- package/dist/common-auth-embedded/routing/ordered.d.ts +47 -0
- package/dist/common-auth-embedded/routing/ordered.js +58 -0
- package/dist/common-auth-embedded/routing/pins.d.ts +22 -0
- package/dist/common-auth-embedded/routing/pins.js +34 -0
- package/dist/common-auth-embedded/routing/sticky.d.ts +158 -0
- package/dist/common-auth-embedded/routing/sticky.js +339 -0
- package/dist/common-auth-embedded/source-output.json +1090 -0
- package/dist/common-auth-embedded/store/attribution.d.ts +28 -0
- package/dist/common-auth-embedded/store/attribution.js +60 -0
- package/dist/common-auth-embedded/store/errors.d.ts +55 -0
- package/dist/common-auth-embedded/store/errors.js +38 -0
- package/dist/common-auth-embedded/store/hooks.d.ts +12 -0
- package/dist/common-auth-embedded/store/hooks.js +34 -0
- package/dist/common-auth-embedded/store/identity.d.ts +39 -0
- package/dist/common-auth-embedded/store/identity.js +79 -0
- package/dist/common-auth-embedded/store/index.d.ts +21 -0
- package/dist/common-auth-embedded/store/index.js +7 -0
- package/dist/common-auth-embedded/store/mutate.d.ts +189 -0
- package/dist/common-auth-embedded/store/mutate.js +500 -0
- package/dist/common-auth-embedded/store/pool.d.ts +196 -0
- package/dist/common-auth-embedded/store/pool.js +120 -0
- package/dist/common-auth-embedded/store/provider-state.d.ts +131 -0
- package/dist/common-auth-embedded/store/provider-state.js +226 -0
- package/dist/common-auth-embedded/store/publication.d.ts +47 -0
- package/dist/common-auth-embedded/store/publication.js +304 -0
- package/dist/common-auth-embedded/store/pull.d.ts +36 -0
- package/dist/common-auth-embedded/store/pull.js +143 -0
- package/dist/common-auth-embedded/store/refresh-lock.d.ts +63 -0
- package/dist/common-auth-embedded/store/refresh-lock.js +136 -0
- package/dist/common-auth-embedded/store/refresh.d.ts +72 -0
- package/dist/common-auth-embedded/store/refresh.js +225 -0
- package/dist/common-auth-embedded/store/reserved.js +13 -0
- package/dist/common-auth-embedded/store/rows.d.ts +313 -0
- package/dist/common-auth-embedded/store/rows.js +1258 -0
- package/dist/common-auth-embedded/store/runtime.d.ts +36 -0
- package/dist/common-auth-embedded/store/runtime.js +68 -0
- package/dist/common-auth-embedded/store/schema.d.ts +443 -0
- package/dist/common-auth-embedded/store/schema.js +754 -0
- package/dist/common-auth-embedded/store/settings.d.ts +63 -0
- package/dist/common-auth-embedded/store/settings.js +120 -0
- package/dist/common-auth-embedded/store/torn.d.ts +78 -0
- package/dist/common-auth-embedded/store/torn.js +294 -0
- package/dist/common-auth-embedded/util/any-signal.js +42 -0
- package/dist/common-auth-runtime.d.ts +73 -0
- package/dist/common-auth-runtime.d.ts.map +1 -0
- package/dist/common-auth-runtime.js +65 -0
- package/dist/common-auth-runtime.js.map +1 -0
- package/dist/credential-redaction.d.ts +13 -0
- package/dist/credential-redaction.d.ts.map +1 -0
- package/dist/credential-redaction.js +230 -0
- package/dist/credential-redaction.js.map +1 -0
- package/dist/fetch-timeout.d.ts +4 -2
- package/dist/fetch-timeout.d.ts.map +1 -1
- package/dist/fetch-timeout.js +121 -14
- package/dist/fetch-timeout.js.map +1 -1
- package/dist/fingerprint.d.ts +3 -3
- package/dist/fingerprint.d.ts.map +1 -1
- package/dist/fingerprint.js +4 -4
- package/dist/fingerprint.js.map +1 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -1
- package/dist/model-registry.d.ts +16 -0
- package/dist/model-registry.d.ts.map +1 -1
- package/dist/model-registry.js +242 -30
- package/dist/model-registry.js.map +1 -1
- package/dist/quota-manager.d.ts.map +1 -1
- package/dist/quota-manager.js +35 -10
- package/dist/quota-manager.js.map +1 -1
- package/dist/quota-presentation.d.ts +10 -0
- package/dist/quota-presentation.d.ts.map +1 -0
- package/dist/quota-presentation.js +60 -0
- package/dist/quota-presentation.js.map +1 -0
- package/dist/quota-types.d.ts +2 -0
- package/dist/quota-types.d.ts.map +1 -1
- package/dist/rotation.d.ts +8 -0
- package/dist/rotation.d.ts.map +1 -1
- package/dist/rotation.js +24 -0
- package/dist/rotation.js.map +1 -1
- package/dist/transform/agy-generation.d.ts +3 -0
- package/dist/transform/agy-generation.d.ts.map +1 -0
- package/dist/transform/agy-generation.js +28 -0
- package/dist/transform/agy-generation.js.map +1 -0
- package/dist/transform/claude.d.ts +7 -3
- package/dist/transform/claude.d.ts.map +1 -1
- package/dist/transform/claude.js +8 -2
- package/dist/transform/claude.js.map +1 -1
- package/dist/transform/index.d.ts +1 -0
- package/dist/transform/index.d.ts.map +1 -1
- package/dist/transform/index.js +1 -0
- package/dist/transform/index.js.map +1 -1
- package/dist/transform/model-resolver.d.ts +2 -1
- package/dist/transform/model-resolver.d.ts.map +1 -1
- package/dist/transform/model-resolver.js +46 -5
- package/dist/transform/model-resolver.js.map +1 -1
- package/dist/transform/types.d.ts +1 -1
- package/dist/transform/types.d.ts.map +1 -1
- package/dist/vault-account-source.d.ts +183 -0
- package/dist/vault-account-source.d.ts.map +1 -0
- package/dist/vault-account-source.js +296 -0
- package/dist/vault-account-source.js.map +1 -0
- package/dist/vault-enrollment-authority.d.ts +16 -0
- package/dist/vault-enrollment-authority.d.ts.map +1 -0
- package/dist/vault-enrollment-authority.js +19 -0
- package/dist/vault-enrollment-authority.js.map +1 -0
- package/dist/vault-family.d.ts +11 -0
- package/dist/vault-family.d.ts.map +1 -0
- package/dist/vault-family.js +24 -0
- package/dist/vault-family.js.map +1 -0
- package/dist/vault-provider-state.d.ts +162 -0
- package/dist/vault-provider-state.d.ts.map +1 -0
- package/dist/vault-provider-state.js +422 -0
- package/dist/vault-provider-state.js.map +1 -0
- package/package.json +39 -2
|
@@ -0,0 +1,831 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract of the Antigravity account repository. The foundation uses the
|
|
3
|
+
* public lease-backed pool store of @cortexkit/common-auth (its `./store`
|
|
4
|
+
* entry). Atomic credential replacement additionally requires a store that
|
|
5
|
+
* exposes the credential-write attribution API described at
|
|
6
|
+
* `AccountRepository.replaceCredential`.
|
|
7
|
+
*
|
|
8
|
+
* The repository replaces whole-file snapshots of `antigravity-accounts.json`
|
|
9
|
+
* with typed operations on individual rows. A row is addressed by a `RowRef`
|
|
10
|
+
* rather than by its position, because positions move under reorder and
|
|
11
|
+
* removal while a ref names one credential of one row: work started for a
|
|
12
|
+
* credential that has since been replaced or removed is refused instead of
|
|
13
|
+
* landing on its successor.
|
|
14
|
+
*
|
|
15
|
+
* Persisted data has four owners:
|
|
16
|
+
* - the store's own roster and credential entries: the bare refresh token,
|
|
17
|
+
* the effective enabled flag and the row order;
|
|
18
|
+
* - provider metadata (`ProviderStateEnvelope`), kept beside the credential
|
|
19
|
+
* in the store's state file. The part of it that describes the signed-in
|
|
20
|
+
* account (see `CREDENTIAL_BOUND_METADATA_FIELDS`) is covered by the
|
|
21
|
+
* store's credential stamp, so a writer that edits it without knowing the
|
|
22
|
+
* stamp makes the value disappear from reads instead of attaching it to
|
|
23
|
+
* the wrong account;
|
|
24
|
+
* - the latest quota reading (`QuotaState`), kept in the row's entry in the
|
|
25
|
+
* store's config file;
|
|
26
|
+
* - account selection (`RoutingSettings`), kept as a plugin settings key in
|
|
27
|
+
* the store's config file.
|
|
28
|
+
*
|
|
29
|
+
* Every shape below that carries `extensions` keeps JSON it does not
|
|
30
|
+
* recognise there, so a file written by a newer build survives a read and
|
|
31
|
+
* rewrite by this one. Optional fields distinguish absent (key missing) from
|
|
32
|
+
* `null`; the codecs never collapse one into the other. Readers treat an
|
|
33
|
+
* optional `null` like absent when they project the data for routing.
|
|
34
|
+
*
|
|
35
|
+
* Credential epochs and identities. The store gives every credential a row
|
|
36
|
+
* holds an epoch number (common-auth `dist/store/attribution.d.ts`,
|
|
37
|
+
* `Attribution`): `add` and `replace` start a new epoch, while refresh and
|
|
38
|
+
* `rotate` keep it. An id that is removed and added again starts past every
|
|
39
|
+
* epoch it held before, in any process. A row without a per-row entry counts
|
|
40
|
+
* as epoch 1. The recorded identity is the account id the provider reported
|
|
41
|
+
* for the credential. Within one epoch it can only go from absent to one
|
|
42
|
+
* value: `recordIdentity`, `rotate`, a re-`add` of the same secret and a
|
|
43
|
+
* refresh all refuse a different identity (`identity-mismatch`, or
|
|
44
|
+
* `identity-contradicted` for a refresh) rather than overwrite it
|
|
45
|
+
* (`dist/store/rows.js` `recordRowIdentity`, `rotateRow`, `addRow`;
|
|
46
|
+
* `dist/store/refresh.d.ts`).
|
|
47
|
+
*
|
|
48
|
+
* Locks. The store takes, in this order and releases in reverse: the row
|
|
49
|
+
* lock `row-<encodeURIComponent(identity ?? id)>` at the state path
|
|
50
|
+
* (`dist/store/runtime.js` `rowLockSpec`), the provider lock (by default
|
|
51
|
+
* `provider-antigravity` at the state path, `dist/store/pool.js`), any extra
|
|
52
|
+
* locks the caller passes, then the `save` locks at the config path and then
|
|
53
|
+
* the state path. A refresh holds the store's `save` locks only while it
|
|
54
|
+
* reads and while it commits, never across the token exchange
|
|
55
|
+
* (`dist/store/refresh.d.ts` `refreshRow`).
|
|
56
|
+
*/
|
|
57
|
+
import type { AccountModelFamily, CooldownReason } from './account-types.ts';
|
|
58
|
+
export type JsonPrimitive = string | number | boolean | null;
|
|
59
|
+
export type JsonValue = JsonPrimitive | JsonValue[] | JsonObject;
|
|
60
|
+
export interface JsonObject {
|
|
61
|
+
[key: string]: JsonValue;
|
|
62
|
+
}
|
|
63
|
+
/** Provider name the pool store is opened with; keys its provider-wide lock. */
|
|
64
|
+
export declare const ACCOUNT_STORE_PROVIDER = "antigravity";
|
|
65
|
+
/** Schema version written inside `ProviderStateEnvelope`. */
|
|
66
|
+
export declare const PROVIDER_STATE_SCHEMA_VERSION = 1;
|
|
67
|
+
/** Schema version written inside `QuotaState`. */
|
|
68
|
+
export declare const QUOTA_STATE_SCHEMA_VERSION = 1;
|
|
69
|
+
/** Schema version written inside `RoutingSettings`. */
|
|
70
|
+
export declare const ROUTING_SETTINGS_SCHEMA_VERSION = 1;
|
|
71
|
+
/** Settings key holding `RoutingSettings`. */
|
|
72
|
+
export declare const ROUTING_SETTINGS_KEY = "antigravityRouting";
|
|
73
|
+
/**
|
|
74
|
+
* Settings key holding the `ManagementRecord` of a migration or a multi-row
|
|
75
|
+
* destructive operation. Ordinary row operations never write it.
|
|
76
|
+
*/
|
|
77
|
+
export declare const MANAGEMENT_SETTINGS_KEY = "antigravityManagement";
|
|
78
|
+
/** Lock name, at the config path, guarding `MANAGEMENT_SETTINGS_KEY`. */
|
|
79
|
+
export declare const MANAGEMENT_LOCK_NAME = "antigravity-management";
|
|
80
|
+
/**
|
|
81
|
+
* Prefix of the per-account lock passed as a refresh's `providerLock`, in
|
|
82
|
+
* place of the store-wide `provider-antigravity` lock. It must differ from the
|
|
83
|
+
* store's `row-` prefix: the same refresh already holds the row lock, and a
|
|
84
|
+
* provider lock with the same name and path would wait on itself.
|
|
85
|
+
*/
|
|
86
|
+
export declare const REFRESH_PROVIDER_LOCK_PREFIX = "agy-refresh-";
|
|
87
|
+
/** Lock name the pre-store writers hold on `antigravity-accounts.json`. */
|
|
88
|
+
export declare const LEGACY_ACCOUNTS_LOCK_NAME = "accounts";
|
|
89
|
+
/** Lease of that lock while the migration holds it. */
|
|
90
|
+
export declare const LEGACY_ACCOUNTS_LOCK_TTL_MS = 10000;
|
|
91
|
+
/**
|
|
92
|
+
* Names one credential of one row: its local id, the credential epoch the
|
|
93
|
+
* store assigned it (1 for a row without a per-row entry) and the identity
|
|
94
|
+
* recorded for it, as explained at the top of this file. Leaving `identity`
|
|
95
|
+
* out means "the row had none recorded", never "any identity". A row's
|
|
96
|
+
* position in the roster is never part of a ref.
|
|
97
|
+
*/
|
|
98
|
+
export interface RowRef {
|
|
99
|
+
readonly id: string;
|
|
100
|
+
readonly credentialEpoch: number;
|
|
101
|
+
readonly identity?: string;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* A lock file the store takes: its name and directory path plus optional
|
|
105
|
+
* lease tuning. Same shape as `PoolLockSpec` in common-auth
|
|
106
|
+
* `dist/store/refresh-lock.d.ts`, so it can be passed to the store as is.
|
|
107
|
+
*/
|
|
108
|
+
export interface AccountLockSpec {
|
|
109
|
+
readonly name: string;
|
|
110
|
+
readonly path: string;
|
|
111
|
+
readonly ttlMs?: number;
|
|
112
|
+
readonly timeoutMs?: number;
|
|
113
|
+
readonly retryMs?: number;
|
|
114
|
+
readonly renew?: boolean;
|
|
115
|
+
readonly renewIntervalMs?: number;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* The per-account lock a refresh of `row` passes as its `providerLock` and
|
|
119
|
+
* holds across the token exchange, so refreshes of different accounts run
|
|
120
|
+
* concurrently while two refreshes of one account stay one at a time. It is
|
|
121
|
+
* keyed like the store's row lock (recorded identity, else local id) and
|
|
122
|
+
* URI-encoded so any identity is a safe lock-file name.
|
|
123
|
+
*/
|
|
124
|
+
export declare function refreshProviderLock(statePath: string, row: Pick<RowRef, 'id' | 'identity'>): AccountLockSpec;
|
|
125
|
+
/**
|
|
126
|
+
* The lock the pre-store writers hold on `antigravity-accounts.json`, taken
|
|
127
|
+
* while the migration reads or retires that file. It is released before any
|
|
128
|
+
* store call, so it never sits inside the store's lock order.
|
|
129
|
+
*/
|
|
130
|
+
export declare function legacyAccountsLock(legacyPath: string): AccountLockSpec;
|
|
131
|
+
export type LastSwitchReason = 'rate-limit' | 'initial' | 'rotation';
|
|
132
|
+
export type FingerprintHistoryReason = 'initial' | 'regenerated' | 'restored';
|
|
133
|
+
export interface StoredClientMetadata {
|
|
134
|
+
ideType: string;
|
|
135
|
+
platform: string;
|
|
136
|
+
pluginType: string;
|
|
137
|
+
extensions?: JsonObject;
|
|
138
|
+
}
|
|
139
|
+
export interface StoredFingerprint {
|
|
140
|
+
deviceId: string;
|
|
141
|
+
sessionToken: string;
|
|
142
|
+
userAgent: string;
|
|
143
|
+
apiClient: string;
|
|
144
|
+
clientMetadata: StoredClientMetadata;
|
|
145
|
+
createdAt: number;
|
|
146
|
+
extensions?: JsonObject;
|
|
147
|
+
}
|
|
148
|
+
export interface StoredFingerprintVersion {
|
|
149
|
+
fingerprint: StoredFingerprint;
|
|
150
|
+
timestamp: number;
|
|
151
|
+
reason: FingerprintHistoryReason;
|
|
152
|
+
extensions?: JsonObject;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Requests sent through the account per model family on one day. `date` is
|
|
156
|
+
* the UTC day the counts belong to (`YYYY-MM-DD`, as
|
|
157
|
+
* `new Date(now).toISOString().slice(0, 10)` gives it). Decoding keeps a
|
|
158
|
+
* past day and its counts as stored; only a usage write starts a new day.
|
|
159
|
+
*/
|
|
160
|
+
export interface StoredDailyRequestCounts {
|
|
161
|
+
date: string;
|
|
162
|
+
claude: number;
|
|
163
|
+
gemini: number;
|
|
164
|
+
extensions?: JsonObject;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* When each rate limit on the account ends, in epoch milliseconds, keyed by
|
|
168
|
+
* quota pool (`claude`, `gemini-antigravity`, `gemini-cli`) or by a
|
|
169
|
+
* model-specific key; `null` where an older writer stored one. Every key is
|
|
170
|
+
* kept as stored.
|
|
171
|
+
*/
|
|
172
|
+
export type StoredRateLimitResetTimes = Record<string, number | null>;
|
|
173
|
+
/**
|
|
174
|
+
* Antigravity metadata kept beside a row's credential; it never holds a
|
|
175
|
+
* credential. The fields named in `CREDENTIAL_BOUND_METADATA_FIELDS`
|
|
176
|
+
* describe the account the credential signs in to (its email, projects,
|
|
177
|
+
* device fingerprint, access verdicts and plan tier), so the store's
|
|
178
|
+
* credential stamp covers them; the rest track how this plugin uses the
|
|
179
|
+
* account.
|
|
180
|
+
*/
|
|
181
|
+
export interface ProviderMetadata {
|
|
182
|
+
/** Exactly as received; never case-folded, and never inferred. */
|
|
183
|
+
email?: string | null;
|
|
184
|
+
/** Kept bare here; packed with the refresh token only at host boundaries. */
|
|
185
|
+
projectId?: string | null;
|
|
186
|
+
managedProjectId?: string | null;
|
|
187
|
+
/** Add time shown to the user; the store's own add time is separate. */
|
|
188
|
+
addedAt: number;
|
|
189
|
+
lastUsed: number;
|
|
190
|
+
/**
|
|
191
|
+
* How the pre-store file encoded the enabled flag (absent, true, false or
|
|
192
|
+
* null). The effective flag is the store's own, `value !== false`.
|
|
193
|
+
*/
|
|
194
|
+
enabled?: boolean | null;
|
|
195
|
+
lastSwitchReason?: LastSwitchReason | null;
|
|
196
|
+
rateLimitResetTimes?: StoredRateLimitResetTimes | null;
|
|
197
|
+
coolingDownUntil?: number | null;
|
|
198
|
+
cooldownReason?: CooldownReason | null;
|
|
199
|
+
/** Display label; may hold personal data and must stay out of telemetry. */
|
|
200
|
+
label?: string | null;
|
|
201
|
+
fingerprint?: StoredFingerprint | null;
|
|
202
|
+
/** Kept in the stored array order; never re-sorted or truncated. */
|
|
203
|
+
fingerprintHistory?: StoredFingerprintVersion[] | null;
|
|
204
|
+
verificationRequired?: boolean | null;
|
|
205
|
+
verificationRequiredAt?: number | null;
|
|
206
|
+
verificationRequiredReason?: string | null;
|
|
207
|
+
/** Checked where it is captured; kept here as stored. */
|
|
208
|
+
verificationUrl?: string | null;
|
|
209
|
+
/** `true` excludes the row from routing. */
|
|
210
|
+
accountIneligible?: boolean | null;
|
|
211
|
+
accountIneligibleAt?: number | null;
|
|
212
|
+
accountIneligibleReason?: string | null;
|
|
213
|
+
eligibilityStateUpdatedAt?: number | null;
|
|
214
|
+
/** Upstream tier id exactly as reported, never normalised. */
|
|
215
|
+
capturedTierId?: string | null;
|
|
216
|
+
/** As reported; its absence does not mean the account is unpaid or paid. */
|
|
217
|
+
capturedPaidTierId?: string | null;
|
|
218
|
+
capturedTierAt?: number | null;
|
|
219
|
+
capturedTierSchemaVersion?: number | null;
|
|
220
|
+
dailyRequestCounts?: StoredDailyRequestCounts | null;
|
|
221
|
+
extensions?: JsonObject;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* The `ProviderMetadata` fields that describe the signed-in account rather
|
|
225
|
+
* than this plugin's use of it. The credential stamp covers exactly these.
|
|
226
|
+
*/
|
|
227
|
+
export declare const CREDENTIAL_BOUND_METADATA_FIELDS: readonly ["email", "projectId", "managedProjectId", "fingerprint", "fingerprintHistory", "verificationRequired", "verificationRequiredAt", "verificationRequiredReason", "verificationUrl", "accountIneligible", "accountIneligibleAt", "accountIneligibleReason", "eligibilityStateUpdatedAt", "capturedTierId", "capturedPaidTierId", "capturedTierAt", "capturedTierSchemaVersion"];
|
|
228
|
+
export type CredentialBoundMetadataField = (typeof CREDENTIAL_BOUND_METADATA_FIELDS)[number];
|
|
229
|
+
/**
|
|
230
|
+
* The value the store keeps for a row under the state file's
|
|
231
|
+
* `commonAuthProviderState` key. A newer `schemaVersion` is refused rather
|
|
232
|
+
* than reinterpreted.
|
|
233
|
+
*/
|
|
234
|
+
export interface ProviderStateEnvelope {
|
|
235
|
+
schemaVersion: typeof PROVIDER_STATE_SCHEMA_VERSION;
|
|
236
|
+
metadata: ProviderMetadata;
|
|
237
|
+
extensions?: JsonObject;
|
|
238
|
+
}
|
|
239
|
+
export type QuotaWindowName = 'weekly' | '5h';
|
|
240
|
+
export interface StoredQuotaWindow {
|
|
241
|
+
window: QuotaWindowName;
|
|
242
|
+
remainingFraction: number;
|
|
243
|
+
resetTime: string;
|
|
244
|
+
extensions?: JsonObject;
|
|
245
|
+
}
|
|
246
|
+
export interface StoredQuotaGroup {
|
|
247
|
+
/** Exactly as reported; never rounded. */
|
|
248
|
+
remainingFraction?: number | null;
|
|
249
|
+
/** Upstream reset timestamp string, kept as reported. */
|
|
250
|
+
resetTime?: string | null;
|
|
251
|
+
modelCount: number;
|
|
252
|
+
/** Kept in the reported order. */
|
|
253
|
+
windows?: StoredQuotaWindow[] | null;
|
|
254
|
+
extensions?: JsonObject;
|
|
255
|
+
}
|
|
256
|
+
export interface StoredModelQuota {
|
|
257
|
+
modelId: string;
|
|
258
|
+
displayName?: string | null;
|
|
259
|
+
/** Required key; `null` means the model belongs to no group. */
|
|
260
|
+
group: string | null;
|
|
261
|
+
remainingFraction: number;
|
|
262
|
+
resetTime?: string | null;
|
|
263
|
+
extensions?: JsonObject;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* The latest quota reading, which the store keeps in the row's config entry.
|
|
267
|
+
* Nothing in it authorises a request: `cachedQuotaAccountId` only records
|
|
268
|
+
* which account produced the reading.
|
|
269
|
+
*/
|
|
270
|
+
export interface QuotaState {
|
|
271
|
+
schemaVersion: typeof QUOTA_STATE_SCHEMA_VERSION;
|
|
272
|
+
cachedQuotaAccountId?: string | null;
|
|
273
|
+
cachedQuota?: Record<string, StoredQuotaGroup> | null;
|
|
274
|
+
cachedPerModelQuota?: StoredModelQuota[] | null;
|
|
275
|
+
cachedQuotaUpdatedAt?: number | null;
|
|
276
|
+
extensions?: JsonObject;
|
|
277
|
+
}
|
|
278
|
+
export interface StoredFamilyIndices {
|
|
279
|
+
claude?: number | null;
|
|
280
|
+
gemini?: number | null;
|
|
281
|
+
extensions?: JsonObject;
|
|
282
|
+
}
|
|
283
|
+
export interface StoredFamilyRows {
|
|
284
|
+
claude?: RowRef | null;
|
|
285
|
+
gemini?: RowRef | null;
|
|
286
|
+
extensions?: JsonObject;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Account selection, kept under `ROUTING_SETTINGS_KEY` in the store's config
|
|
290
|
+
* file. The index fields keep the pre-store `activeIndex` and
|
|
291
|
+
* `activeIndexByFamily` values exactly as stored (readers clamp the index to
|
|
292
|
+
* the roster, as the pre-store loader did); the row fields name the selected
|
|
293
|
+
* row for each family independently. A ref that no longer matches a row
|
|
294
|
+
* falls back to the index rules.
|
|
295
|
+
*/
|
|
296
|
+
export interface RoutingSettings {
|
|
297
|
+
schemaVersion: typeof ROUTING_SETTINGS_SCHEMA_VERSION;
|
|
298
|
+
activeIndex?: number | null;
|
|
299
|
+
activeIndexByFamily?: StoredFamilyIndices | null;
|
|
300
|
+
activeRow?: RowRef | null;
|
|
301
|
+
activeRowByFamily?: StoredFamilyRows | null;
|
|
302
|
+
extensions?: JsonObject;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* What the store tells the provider-state replacement hook about a
|
|
306
|
+
* `replace`. Same shape as `ProviderStateReplacement` in common-auth
|
|
307
|
+
* `dist/store/schema.d.ts`. `previousIdentity` is optional because stores
|
|
308
|
+
* without the locked prior-identity field (0.10.0 among them) never pass it.
|
|
309
|
+
*/
|
|
310
|
+
export interface ProviderStateReplacementInfo {
|
|
311
|
+
id: string;
|
|
312
|
+
credentialEpoch: number;
|
|
313
|
+
previousIdentity?: string;
|
|
314
|
+
identity?: string;
|
|
315
|
+
incoming?: unknown;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* The hooks the store calls for the value it keeps beside each credential:
|
|
319
|
+
* validation on every load and write, the digest input for the credential
|
|
320
|
+
* stamp, combining a stored value with an incoming one, and the value a
|
|
321
|
+
* credential replacement leaves. Same shape as `ProviderStateCodec` in
|
|
322
|
+
* common-auth `dist/store/schema.d.ts`, where every hook but `validate` is
|
|
323
|
+
* optional.
|
|
324
|
+
*/
|
|
325
|
+
export interface ProviderStateCodecContract {
|
|
326
|
+
validate(value: unknown): boolean;
|
|
327
|
+
credentialBound?(value: unknown): unknown;
|
|
328
|
+
merge?(onDisk: unknown, incoming: unknown): unknown;
|
|
329
|
+
onReplace?(previous: unknown | undefined, replacement: ProviderStateReplacementInfo): unknown | undefined;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* The provider-state codec this plugin opens the store with: every hook is
|
|
333
|
+
* present. Left out, the store would fall back to its defaults (the incoming
|
|
334
|
+
* value replaces the stored one; a replace keeps only the value handed to
|
|
335
|
+
* it), which would bypass the repository's merge and replacement rules.
|
|
336
|
+
*/
|
|
337
|
+
export interface ConfiguredProviderStateCodec extends ProviderStateCodecContract {
|
|
338
|
+
credentialBound(value: unknown): unknown;
|
|
339
|
+
merge(onDisk: unknown, incoming: unknown): unknown;
|
|
340
|
+
onReplace(previous: unknown | undefined, replacement: ProviderStateReplacementInfo): unknown | undefined;
|
|
341
|
+
}
|
|
342
|
+
/** A credential replacement as the replacement policy sees it. */
|
|
343
|
+
export interface ProviderStateReplacement {
|
|
344
|
+
id: string;
|
|
345
|
+
/** The epoch the new credential starts. */
|
|
346
|
+
credentialEpoch: number;
|
|
347
|
+
/**
|
|
348
|
+
* The known prior identity: what the row had recorded before the replace,
|
|
349
|
+
* read by the store under its locks. Absent when the row recorded none or
|
|
350
|
+
* the store does not supply the field (0.10.0 does not). Without a known
|
|
351
|
+
* prior identity a rule cannot conclude that the new credential belongs
|
|
352
|
+
* to the same account, neither from `identity` alone nor from both being
|
|
353
|
+
* absent, so it must not carry the credential-bound account metadata
|
|
354
|
+
* (`CREDENTIAL_BOUND_METADATA_FIELDS`) across on that basis. This is an
|
|
355
|
+
* input to a retention rule only; it is not the attribution check (see
|
|
356
|
+
* `AccountRepository.replaceCredential`).
|
|
357
|
+
*/
|
|
358
|
+
previousIdentity?: string;
|
|
359
|
+
/** The identity the replace records for the new credential. */
|
|
360
|
+
identity?: string;
|
|
361
|
+
/** The metadata handed to `replace`, already validated. */
|
|
362
|
+
incoming?: ProviderStateEnvelope;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* The repository's rules for combining provider metadata, which the codec
|
|
366
|
+
* factory requires. Both run synchronously under the store's locks and must
|
|
367
|
+
* not call back into the store. A rule that throws refuses the whole write
|
|
368
|
+
* before anything is written.
|
|
369
|
+
*/
|
|
370
|
+
export interface ProviderStatePolicy {
|
|
371
|
+
/**
|
|
372
|
+
* Combines the stored metadata with metadata that arrives with a
|
|
373
|
+
* credential write of the same epoch: a refresh, or an `add` of a secret
|
|
374
|
+
* the pool already holds (the store's own `rotate` also calls it).
|
|
375
|
+
*/
|
|
376
|
+
merge(onDisk: ProviderStateEnvelope, incoming: ProviderStateEnvelope): ProviderStateEnvelope;
|
|
377
|
+
/**
|
|
378
|
+
* The metadata a row keeps once `replace` gives it a new credential;
|
|
379
|
+
* `undefined` clears it. `previous` is the replaced credential's metadata
|
|
380
|
+
* when the row showed any.
|
|
381
|
+
*/
|
|
382
|
+
onReplace(previous: ProviderStateEnvelope | undefined, replacement: ProviderStateReplacement): ProviderStateEnvelope | undefined;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* The hooks the store calls for the quota reading: validation, and folding a
|
|
386
|
+
* new reading into the stored one. Same shape as `QuotaCodec` in common-auth
|
|
387
|
+
* `dist/store/schema.d.ts`.
|
|
388
|
+
*/
|
|
389
|
+
export interface QuotaCodecContract {
|
|
390
|
+
validate(value: unknown): boolean;
|
|
391
|
+
merge(stored: unknown | undefined, observation: unknown): unknown;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Files the repository owns. The pre-store pool file is read only by the
|
|
395
|
+
* migration, which then retires it; everything else lives in a private
|
|
396
|
+
* directory beside it, so a pre-store writer that still runs can never touch
|
|
397
|
+
* the store's credentials or epochs.
|
|
398
|
+
*/
|
|
399
|
+
export interface AccountStorePaths {
|
|
400
|
+
/** The pre-store v4 `antigravity-accounts.json`. */
|
|
401
|
+
legacyPath: string;
|
|
402
|
+
/** `<dirname(legacyPath)>/<basename(legacyPath)>.store/` */
|
|
403
|
+
storeDir: string;
|
|
404
|
+
configPath: string;
|
|
405
|
+
statePath: string;
|
|
406
|
+
migrationPath: string;
|
|
407
|
+
backupsDir: string;
|
|
408
|
+
retiredDir: string;
|
|
409
|
+
transfersDir: string;
|
|
410
|
+
}
|
|
411
|
+
/** What the token exchange is handed: the bare refresh token and the row. */
|
|
412
|
+
export interface AccountTokenExchangeInput {
|
|
413
|
+
refreshToken: string;
|
|
414
|
+
row: AccountRow;
|
|
415
|
+
}
|
|
416
|
+
export interface AccountTokenExchangeResult {
|
|
417
|
+
accessToken: string;
|
|
418
|
+
refreshToken: string;
|
|
419
|
+
expiresAt: number;
|
|
420
|
+
/** Wire identity the provider reported, when it reported one. */
|
|
421
|
+
identity?: string;
|
|
422
|
+
/**
|
|
423
|
+
* Metadata learnt with the new token. Present fields replace the stored
|
|
424
|
+
* ones; omitted fields (projects included) are kept.
|
|
425
|
+
*/
|
|
426
|
+
metadata?: Partial<ProviderMetadata>;
|
|
427
|
+
}
|
|
428
|
+
/** Performs one OAuth refresh against the provider. */
|
|
429
|
+
export type AccountTokenExchange = (input: AccountTokenExchangeInput) => Promise<AccountTokenExchangeResult>;
|
|
430
|
+
export interface AccountRepositoryOptions {
|
|
431
|
+
paths: AccountStorePaths;
|
|
432
|
+
/** Clock for evidence times, usage dates and store leases. */
|
|
433
|
+
now: () => number;
|
|
434
|
+
/** Token exchange used by `refresh`. */
|
|
435
|
+
exchange: AccountTokenExchange;
|
|
436
|
+
}
|
|
437
|
+
export type CreateAccountRepository = (options: AccountRepositoryOptions) => AccountRepository;
|
|
438
|
+
/**
|
|
439
|
+
* What the store proves about a row's credential. Same values as
|
|
440
|
+
* `CredentialStampStatus` in common-auth `dist/store/schema.d.ts`; only
|
|
441
|
+
* `bound` is usable, since the store is opened with credential stamps
|
|
442
|
+
* required.
|
|
443
|
+
*/
|
|
444
|
+
export type AccountCredentialStamp = 'none' | 'bound' | 'missing' | 'malformed' | 'mismatched' | 'legacy';
|
|
445
|
+
export interface AccountCredentialView {
|
|
446
|
+
/** Bare refresh token; never packed with project ids here. */
|
|
447
|
+
refreshToken: string;
|
|
448
|
+
accessToken?: string;
|
|
449
|
+
expiresAt?: number;
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* The provider metadata a row shows. `dropped` means the state file holds a
|
|
453
|
+
* value the row does not show (another writer changed its account-describing
|
|
454
|
+
* part, or the codec refuses it); callers treat that as an error to surface,
|
|
455
|
+
* never as an empty value to regenerate.
|
|
456
|
+
*/
|
|
457
|
+
export type AccountMetadataView = {
|
|
458
|
+
status: 'present';
|
|
459
|
+
metadata: ProviderMetadata;
|
|
460
|
+
} | {
|
|
461
|
+
status: 'absent';
|
|
462
|
+
} | {
|
|
463
|
+
status: 'dropped';
|
|
464
|
+
reason: 'uncovered' | 'invalid';
|
|
465
|
+
};
|
|
466
|
+
export type AccountQuotaView = {
|
|
467
|
+
status: 'present';
|
|
468
|
+
quota: QuotaState;
|
|
469
|
+
} | {
|
|
470
|
+
status: 'absent';
|
|
471
|
+
};
|
|
472
|
+
export interface AccountRow {
|
|
473
|
+
ref: RowRef;
|
|
474
|
+
/** Position in the roster; presentation only. */
|
|
475
|
+
index: number;
|
|
476
|
+
/** The store's effective enabled flag. */
|
|
477
|
+
enabled: boolean;
|
|
478
|
+
disabledReason?: string;
|
|
479
|
+
/** When the store admitted the row; not the user-visible add time. */
|
|
480
|
+
storeAddedAt?: number;
|
|
481
|
+
credential?: AccountCredentialView;
|
|
482
|
+
/** May be refreshed, pulled for, or routed to. */
|
|
483
|
+
usable: boolean;
|
|
484
|
+
stamp: AccountCredentialStamp;
|
|
485
|
+
torn?: true;
|
|
486
|
+
unbound?: true;
|
|
487
|
+
invalid?: 'roster' | 'entry';
|
|
488
|
+
metadata: AccountMetadataView;
|
|
489
|
+
quota: AccountQuotaView;
|
|
490
|
+
}
|
|
491
|
+
export type ManagementKind = 'migration' | 'clear' | 'replace-pool';
|
|
492
|
+
/**
|
|
493
|
+
* A multi-row operation in progress. Admission refuses new work while one is
|
|
494
|
+
* pending; work already admitted finishes. `targets` are row ids, and
|
|
495
|
+
* `progress` names the last durable step, so a restarted process resumes
|
|
496
|
+
* instead of repeating it.
|
|
497
|
+
*/
|
|
498
|
+
export interface ManagementRecord {
|
|
499
|
+
id: string;
|
|
500
|
+
kind: ManagementKind;
|
|
501
|
+
targets: readonly string[];
|
|
502
|
+
progress: {
|
|
503
|
+
step: string;
|
|
504
|
+
completedTargets: readonly string[];
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
export type AccountRepositoryRead = {
|
|
508
|
+
status: 'ready';
|
|
509
|
+
rows: readonly AccountRow[];
|
|
510
|
+
routing?: RoutingSettings;
|
|
511
|
+
} | {
|
|
512
|
+
status: 'pending-migration';
|
|
513
|
+
} | {
|
|
514
|
+
status: 'management-pending';
|
|
515
|
+
management: ManagementRecord;
|
|
516
|
+
} | {
|
|
517
|
+
status: 'error';
|
|
518
|
+
file: 'config' | 'state' | 'settings';
|
|
519
|
+
reason: string;
|
|
520
|
+
};
|
|
521
|
+
/**
|
|
522
|
+
* What a metadata mutator asks for. Clearing is explicit, so a mutator that
|
|
523
|
+
* forgets to return a value never deletes the row's metadata.
|
|
524
|
+
*/
|
|
525
|
+
export type MetadataUpdate = {
|
|
526
|
+
kind: 'set';
|
|
527
|
+
metadata: ProviderMetadata;
|
|
528
|
+
} | {
|
|
529
|
+
kind: 'keep';
|
|
530
|
+
} | {
|
|
531
|
+
kind: 'clear';
|
|
532
|
+
};
|
|
533
|
+
/**
|
|
534
|
+
* A transition mutator may also decline, for example when the metadata it is
|
|
535
|
+
* shown records evidence newer than the evidence the caller acts on; nothing
|
|
536
|
+
* is written, the enabled flag included.
|
|
537
|
+
*/
|
|
538
|
+
export type MetadataTransition = MetadataUpdate | {
|
|
539
|
+
kind: 'decline';
|
|
540
|
+
};
|
|
541
|
+
/**
|
|
542
|
+
* Runs under the row and store locks with a private copy of the current
|
|
543
|
+
* metadata (undefined when the row shows none). It must not call back into
|
|
544
|
+
* the repository.
|
|
545
|
+
*/
|
|
546
|
+
export type MetadataMutator = (current: ProviderMetadata | undefined, row: AccountRow) => MetadataUpdate | Promise<MetadataUpdate>;
|
|
547
|
+
export type MetadataTransitionMutator = (current: ProviderMetadata | undefined, row: AccountRow) => MetadataTransition | Promise<MetadataTransition>;
|
|
548
|
+
export interface AccountLoginInput {
|
|
549
|
+
/** A fresh UUID for a new row; the result names the row actually used. */
|
|
550
|
+
id: string;
|
|
551
|
+
/** Bare refresh token. */
|
|
552
|
+
refreshToken: string;
|
|
553
|
+
/** Authenticated wire identity, when the login established one. */
|
|
554
|
+
identity?: string;
|
|
555
|
+
metadata: ProviderMetadata;
|
|
556
|
+
}
|
|
557
|
+
export interface AccountLoginResult {
|
|
558
|
+
/** Authoritative: an existing row's ref when the secret was already held. */
|
|
559
|
+
ref: RowRef;
|
|
560
|
+
/**
|
|
561
|
+
* `rotated` when the pool already held this secret: the retry keeps that
|
|
562
|
+
* row's credential epoch.
|
|
563
|
+
*/
|
|
564
|
+
outcome: 'added' | 'added-disabled' | 'completed' | 'rotated';
|
|
565
|
+
}
|
|
566
|
+
export interface AccountReplaceInput {
|
|
567
|
+
refreshToken: string;
|
|
568
|
+
identity?: string;
|
|
569
|
+
metadata?: ProviderMetadata;
|
|
570
|
+
/**
|
|
571
|
+
* Whether a disabled row stays disabled after the new credential lands.
|
|
572
|
+
* OpenCode 1 keeps the user's choice; other hosts decide their own policy.
|
|
573
|
+
*/
|
|
574
|
+
disabled: 'keep' | 'enable';
|
|
575
|
+
}
|
|
576
|
+
export type AccountRefreshOutcome = {
|
|
577
|
+
status: 'rotated';
|
|
578
|
+
ref: RowRef;
|
|
579
|
+
accessToken: string;
|
|
580
|
+
expiresAt: number;
|
|
581
|
+
} | {
|
|
582
|
+
/**
|
|
583
|
+
* The provider answered for another account. The successor is kept,
|
|
584
|
+
* disabled and bound to the expected identity, and no bearer is handed
|
|
585
|
+
* out until a validated `replaceCredential`.
|
|
586
|
+
*/
|
|
587
|
+
status: 'identity-contradicted';
|
|
588
|
+
ref: RowRef;
|
|
589
|
+
expectedIdentity: string;
|
|
590
|
+
returnedIdentity: string;
|
|
591
|
+
} | {
|
|
592
|
+
status: 'refused';
|
|
593
|
+
ref: RowRef;
|
|
594
|
+
reason: string;
|
|
595
|
+
};
|
|
596
|
+
export interface AccountRefreshOptions {
|
|
597
|
+
/** Checked before locking, after the locked re-read and at commit. */
|
|
598
|
+
refuse?: (row: AccountRow) => string | undefined | Promise<string | undefined>;
|
|
599
|
+
}
|
|
600
|
+
export interface AccountEnableInput {
|
|
601
|
+
enabled: boolean;
|
|
602
|
+
/** The store's `disabledReason` when disabling. */
|
|
603
|
+
reason?: string;
|
|
604
|
+
/** A user enable refuses an ineligible account; a system one may not. */
|
|
605
|
+
actor: 'user' | 'system';
|
|
606
|
+
metadata?: MetadataTransitionMutator;
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Evidence about account access, timestamped by when it was observed so a
|
|
610
|
+
* late verdict cannot undo a newer one.
|
|
611
|
+
*/
|
|
612
|
+
export type AccessVerdict = {
|
|
613
|
+
kind: 'verification-required';
|
|
614
|
+
observedAt: number;
|
|
615
|
+
reason?: string;
|
|
616
|
+
verificationUrl?: string;
|
|
617
|
+
} | {
|
|
618
|
+
kind: 'ineligible';
|
|
619
|
+
observedAt: number;
|
|
620
|
+
reason: string;
|
|
621
|
+
} | {
|
|
622
|
+
kind: 'cleared';
|
|
623
|
+
observedAt: number;
|
|
624
|
+
enable: boolean;
|
|
625
|
+
};
|
|
626
|
+
export interface AccountTransitionResult {
|
|
627
|
+
ref: RowRef;
|
|
628
|
+
declined?: true;
|
|
629
|
+
metadataOutcome?: 'updated' | 'cleared' | 'unchanged';
|
|
630
|
+
metadata?: ProviderMetadata;
|
|
631
|
+
}
|
|
632
|
+
export interface AccountMetadataResult {
|
|
633
|
+
ref: RowRef;
|
|
634
|
+
outcome: 'updated' | 'cleared' | 'unchanged';
|
|
635
|
+
metadata?: ProviderMetadata;
|
|
636
|
+
}
|
|
637
|
+
export interface ProjectObservation {
|
|
638
|
+
projectId?: string | null;
|
|
639
|
+
managedProjectId?: string | null;
|
|
640
|
+
}
|
|
641
|
+
export interface FingerprintObservation {
|
|
642
|
+
fingerprint: StoredFingerprint;
|
|
643
|
+
history: readonly StoredFingerprintVersion[];
|
|
644
|
+
}
|
|
645
|
+
export interface TierObservation {
|
|
646
|
+
observedAt: number;
|
|
647
|
+
tierId: string | null;
|
|
648
|
+
paidTierId: string | null;
|
|
649
|
+
schemaVersion: number;
|
|
650
|
+
}
|
|
651
|
+
export type CooldownObservation = {
|
|
652
|
+
until: number;
|
|
653
|
+
reason: CooldownReason;
|
|
654
|
+
} | null;
|
|
655
|
+
export interface UsageObservation {
|
|
656
|
+
family: AccountModelFamily;
|
|
657
|
+
at: number;
|
|
658
|
+
}
|
|
659
|
+
export interface AccountUsageResult {
|
|
660
|
+
ref: RowRef;
|
|
661
|
+
lastUsed: number;
|
|
662
|
+
dailyRequestCounts: StoredDailyRequestCounts;
|
|
663
|
+
}
|
|
664
|
+
/** Which selection `selectAccount` changes. */
|
|
665
|
+
export type RoutingTarget = 'active' | AccountModelFamily;
|
|
666
|
+
export interface ManagementReceipt {
|
|
667
|
+
management: ManagementRecord;
|
|
668
|
+
outcome: 'completed' | 'pending';
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Same failure kinds as `PoolFailureKind` in common-auth
|
|
672
|
+
* `dist/store/errors.d.ts`, followed by the repository's own.
|
|
673
|
+
*/
|
|
674
|
+
export type AccountRepositoryFailureKind = 'lock-contention' | 'lock-ownership' | 'pending-migration' | 'load-error' | 'snapshot-contended' | 'publication-sync' | 'publication-incomplete' | 'publication-mismatch' | 'row-staged' | 'credential-exists' | 'unknown-row' | 'invalid-row' | 'invalid-input' | 'id-exists' | 'id-removed' | 'type-mismatch' | 'no-credential' | 'row-disabled' | 'row-protected' | 'duplicate-identity' | 'identity-mismatch' | 'identity-contradicted' | 'endpoint-mismatch' | 'row-key-changed' | 'invalid-order' | 'refresh-stamp-ahead' | 'unbound-credential' | 'attribution' | 'provider' | 'pull' | 'invalid-quota' | 'invalid-provider-state' | 'after-persist-hook' | 'unexpected' | 'management-pending' | 'replacement-unavailable' | 'metadata-dropped' | 'account-ineligible' | 'duplicate-secret' | 'disposed';
|
|
675
|
+
export type AccountRepositoryOperation = 'read' | 'login' | 'replaceCredential' | 'refresh' | 'recordIdentity' | 'setEnabled' | 'recordAccessVerdict' | 'updateMetadata' | 'recordProject' | 'recordFingerprint' | 'recordTier' | 'recordCooldown' | 'recordRateLimits' | 'recordSwitch' | 'recordUsage' | 'recordQuota' | 'selectAccount' | 'reorder' | 'remove' | 'clear' | 'replacePool' | 'flush';
|
|
676
|
+
/**
|
|
677
|
+
* How an operation failed. Messages never contain credentials. `ambiguous`
|
|
678
|
+
* marks a write that may or may not have landed (the usage increment
|
|
679
|
+
* included): callers reload and report instead of replaying it.
|
|
680
|
+
*/
|
|
681
|
+
export interface AccountRepositoryFailure {
|
|
682
|
+
operation: AccountRepositoryOperation;
|
|
683
|
+
kind: AccountRepositoryFailureKind;
|
|
684
|
+
retryable: boolean;
|
|
685
|
+
ambiguous: boolean;
|
|
686
|
+
rowId?: string;
|
|
687
|
+
message: string;
|
|
688
|
+
}
|
|
689
|
+
export interface AccountFlushReport {
|
|
690
|
+
/** Writes that completed while draining. */
|
|
691
|
+
completed: number;
|
|
692
|
+
failures: readonly AccountRepositoryFailure[];
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* Typed operations on the Antigravity account pool.
|
|
696
|
+
*
|
|
697
|
+
* Every operation about an existing credential takes the `RowRef` the
|
|
698
|
+
* caller's evidence was gathered under. The repository refuses it with
|
|
699
|
+
* `attribution` when the row's epoch or recorded identity has changed since
|
|
700
|
+
* then, and with `unknown-row` when the row has been removed. Each method
|
|
701
|
+
* below names the store API that makes this check under the row and save
|
|
702
|
+
* locks before anything is written. Ordinary operations take only the
|
|
703
|
+
* store's locks; only `clear` and `replacePool` write a `ManagementRecord`,
|
|
704
|
+
* the resumable record of a destructive multi-row or migration operation.
|
|
705
|
+
*/
|
|
706
|
+
export interface AccountRepository {
|
|
707
|
+
/** Reads the pool and settings without writing or firing quota pulls. */
|
|
708
|
+
read(): Promise<AccountRepositoryRead>;
|
|
709
|
+
/** Resolves once every quota pull fired so far has settled. */
|
|
710
|
+
settled(): Promise<void>;
|
|
711
|
+
/**
|
|
712
|
+
* Admits a login: matches an existing row by exact email, then by secret;
|
|
713
|
+
* contradictory matches refuse. It names no existing credential, so it
|
|
714
|
+
* takes no ref; the returned ref is authoritative.
|
|
715
|
+
*/
|
|
716
|
+
login(input: AccountLoginInput): Promise<AccountLoginResult>;
|
|
717
|
+
/**
|
|
718
|
+
* Gives the row in `expected` a new credential and a new epoch
|
|
719
|
+
* (re-authentication). Quota, rate limits, cooldown and access blocks of
|
|
720
|
+
* the old credential are cleared; same-account display fields are kept.
|
|
721
|
+
*
|
|
722
|
+
* The repository must refuse it (`attribution`, nothing written) unless,
|
|
723
|
+
* under the row and save locks and before anything is written, the row
|
|
724
|
+
* still holds exactly `expected`: the same epoch and the same recorded
|
|
725
|
+
* identity, an absent identity matching only an absent one.
|
|
726
|
+
*
|
|
727
|
+
* Requires a store exposing atomic credential-write attribution:
|
|
728
|
+
* `RowWriteOptions.attribution` on `replace` (`dist/store/rows.d.ts`),
|
|
729
|
+
* which common-auth 0.10.0 lacks. The repository passes `expected`'s
|
|
730
|
+
* epoch and identity exactly as that attribution; the store compares them
|
|
731
|
+
* under the row and store locks before completing an interrupted replace,
|
|
732
|
+
* before any write and before the replacement hook, and refuses with
|
|
733
|
+
* `attribution` (retryable, nothing written). Without that API this
|
|
734
|
+
* method has no conforming implementation. The hook's `previousIdentity`
|
|
735
|
+
* is only an input to the retention rule, never this check.
|
|
736
|
+
*/
|
|
737
|
+
replaceCredential(expected: RowRef, input: AccountReplaceInput): Promise<{
|
|
738
|
+
ref: RowRef;
|
|
739
|
+
}>;
|
|
740
|
+
/**
|
|
741
|
+
* Exchanges the row's refresh token for a new access token (and possibly
|
|
742
|
+
* a new refresh token). The epoch names the login or replacement that put
|
|
743
|
+
* the credential there, not each refresh, so a refresh keeps it; metadata
|
|
744
|
+
* the exchange leaves out (projects included) is kept. This is the only
|
|
745
|
+
* path by which a successor of an existing credential reaches the store.
|
|
746
|
+
*
|
|
747
|
+
* The row lock and the per-account lock from `refreshProviderLock` are
|
|
748
|
+
* held across the exchange; the save locks are held only while the store
|
|
749
|
+
* reads the row and while it commits the files. The store calls
|
|
750
|
+
* `refuse(row)` before locking, on the locked re-read and at commit
|
|
751
|
+
* (`dist/store/refresh.d.ts`); the repository refuses there when the
|
|
752
|
+
* row's epoch or identity differs from `ref`, and the store then drops the
|
|
753
|
+
* refreshed token instead of committing it to a changed or replaced row.
|
|
754
|
+
*/
|
|
755
|
+
refresh(ref: RowRef, options?: AccountRefreshOptions): Promise<AccountRefreshOutcome>;
|
|
756
|
+
/**
|
|
757
|
+
* Records an authenticated identity lookup for the credential in `ref`.
|
|
758
|
+
* Fence: the store's `recordIdentity` attribution checks the epoch; a
|
|
759
|
+
* different identity already recorded refuses with `identity-mismatch`.
|
|
760
|
+
*/
|
|
761
|
+
recordIdentity(ref: RowRef, identity: string): Promise<{
|
|
762
|
+
ref: RowRef;
|
|
763
|
+
}>;
|
|
764
|
+
/**
|
|
765
|
+
* Enables or disables a row, optionally changing its metadata in the same
|
|
766
|
+
* crash-consistent write. Fence: the store's `enable`/`disable`
|
|
767
|
+
* `attribution` option (epoch and identity).
|
|
768
|
+
*/
|
|
769
|
+
setEnabled(ref: RowRef, input: AccountEnableInput): Promise<AccountTransitionResult>;
|
|
770
|
+
/**
|
|
771
|
+
* Applies access evidence (verification, eligibility) together with the
|
|
772
|
+
* enabled flag. Fence: as `setEnabled`.
|
|
773
|
+
*/
|
|
774
|
+
recordAccessVerdict(ref: RowRef, verdict: AccessVerdict): Promise<AccountTransitionResult>;
|
|
775
|
+
/**
|
|
776
|
+
* Changes metadata only; the credential and its stamp status stay. Fence
|
|
777
|
+
* for this and every metadata `record*` method below: the store's
|
|
778
|
+
* `updateProviderState` fence (epoch and identity).
|
|
779
|
+
*/
|
|
780
|
+
updateMetadata(ref: RowRef, mutator: MetadataMutator): Promise<AccountMetadataResult>;
|
|
781
|
+
recordProject(ref: RowRef, observation: ProjectObservation): Promise<AccountMetadataResult>;
|
|
782
|
+
recordFingerprint(ref: RowRef, observation: FingerprintObservation): Promise<AccountMetadataResult>;
|
|
783
|
+
recordTier(ref: RowRef, observation: TierObservation): Promise<AccountMetadataResult>;
|
|
784
|
+
recordCooldown(ref: RowRef, observation: CooldownObservation): Promise<AccountMetadataResult>;
|
|
785
|
+
/**
|
|
786
|
+
* Merges reset times key by key, keeping the later time for each key.
|
|
787
|
+
*/
|
|
788
|
+
recordRateLimits(ref: RowRef, resets: Readonly<StoredRateLimitResetTimes>): Promise<AccountMetadataResult>;
|
|
789
|
+
recordSwitch(ref: RowRef, reason: LastSwitchReason): Promise<AccountMetadataResult>;
|
|
790
|
+
/**
|
|
791
|
+
* Adds one request for the family to the account's count for the current
|
|
792
|
+
* UTC day (from the injected clock), starting from zero when the stored
|
|
793
|
+
* `date` is another day, and keeps the later of the stored and given
|
|
794
|
+
* `lastUsed`. It runs under the row lock. A failure that leaves unknown
|
|
795
|
+
* whether the increment landed is reported as `ambiguous` and is never
|
|
796
|
+
* retried, so a request is never counted twice.
|
|
797
|
+
*/
|
|
798
|
+
recordUsage(ref: RowRef, observation: UsageObservation): Promise<AccountUsageResult>;
|
|
799
|
+
/**
|
|
800
|
+
* Records a quota reading for the credential in `ref`, separately from
|
|
801
|
+
* `recordTier`: the two are independent writes. Fence: the store's
|
|
802
|
+
* `recordQuota` attribution (epoch and identity).
|
|
803
|
+
*/
|
|
804
|
+
recordQuota(ref: RowRef, observation: QuotaState): Promise<void>;
|
|
805
|
+
/** Points a selection at a row (`null` clears it) in the routing settings. */
|
|
806
|
+
selectAccount(target: RoutingTarget, row: RowRef | null): Promise<void>;
|
|
807
|
+
/** Sets the roster order; `ids` names every row exactly once. */
|
|
808
|
+
reorder(ids: readonly string[]): Promise<void>;
|
|
809
|
+
/**
|
|
810
|
+
* Removes one row; the store keeps its epochs retired, so a later add of
|
|
811
|
+
* the same id starts past them. Fence: the store's `remove` `protect`
|
|
812
|
+
* callback, which sees the row under every lock before anything is
|
|
813
|
+
* written.
|
|
814
|
+
*/
|
|
815
|
+
remove(ref: RowRef): Promise<void>;
|
|
816
|
+
/** Removes every row as one journaled operation. */
|
|
817
|
+
clear(): Promise<ManagementReceipt>;
|
|
818
|
+
/**
|
|
819
|
+
* Replaces the account list through the store's single configuration write.
|
|
820
|
+
* Prepared accounts remain disabled until that write commits. Refresh tokens
|
|
821
|
+
* stay in an owner-only transfer file until verification; interrupted calls
|
|
822
|
+
* replay the recorded write plan. If the store cannot publish the entire list
|
|
823
|
+
* at once, replacement of a non-empty pool refuses without changing it.
|
|
824
|
+
*/
|
|
825
|
+
replacePool(inputs: readonly AccountLoginInput[]): Promise<ManagementReceipt>;
|
|
826
|
+
/** Waits for queued writes and reports every failure among them. */
|
|
827
|
+
flush(): Promise<AccountFlushReport>;
|
|
828
|
+
/** Flushes, then refuses further writes (`disposed`). */
|
|
829
|
+
dispose(): Promise<AccountFlushReport>;
|
|
830
|
+
}
|
|
831
|
+
//# sourceMappingURL=account-repository-types.d.ts.map
|