@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,28 @@
|
|
|
1
|
+
import { type StoreRuntime } from './runtime.js';
|
|
2
|
+
/**
|
|
3
|
+
* What a pull or refresh captured about its row (named by id alongside) when
|
|
4
|
+
* it was issued. A result applies only while the row with that id still has
|
|
5
|
+
* this credential epoch and this recorded identity; a replaced credential
|
|
6
|
+
* bumps the epoch, so work issued for the old one is discarded.
|
|
7
|
+
*
|
|
8
|
+
* The epoch names one credential lineage of the row: a credential given by
|
|
9
|
+
* `add` or `replace`, through every refresh and `rotate` of it, which keep
|
|
10
|
+
* the epoch. Since 0.8.0 that holds across removal too: a row added under an
|
|
11
|
+
* id the pool held before starts past every epoch that id held (the store
|
|
12
|
+
* records them when it drops a row, in the config file, so every process
|
|
13
|
+
* sees it), so an attribution taken for a removed row is refused once the id
|
|
14
|
+
* is added again, even with the same identity. Writers older than 0.8.0
|
|
15
|
+
* start a re-added id at epoch 1 again, and a writer that does not know the
|
|
16
|
+
* pool can remove and re-add a row without the store seeing it; work
|
|
17
|
+
* attributed across either may still apply to the new credential.
|
|
18
|
+
*/
|
|
19
|
+
export interface Attribution {
|
|
20
|
+
credentialEpoch: number;
|
|
21
|
+
identity?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Merges a quota observation into a row's stored map under the store locks,
|
|
25
|
+
* after attribution passes. Needs no row lock, so it is permitted from
|
|
26
|
+
* inside hooks. Clears needs-first-reading on success.
|
|
27
|
+
*/
|
|
28
|
+
export declare function recordQuota(rt: StoreRuntime, id: string, attribution: Attribution, observation: unknown): Promise<void>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { PoolOperationError } from './errors.js';
|
|
2
|
+
import { toFailure, withTransaction } from './mutate.js';
|
|
3
|
+
import { LockStack } from './refresh-lock.js';
|
|
4
|
+
import { refusal, requireBound, unknownRow, } from './runtime.js';
|
|
5
|
+
import { isCredentialEpoch } from './schema.js';
|
|
6
|
+
/**
|
|
7
|
+
* Merges a quota observation into a row's stored map under the store locks,
|
|
8
|
+
* after attribution passes. Needs no row lock, so it is permitted from
|
|
9
|
+
* inside hooks. Clears needs-first-reading on success.
|
|
10
|
+
*/
|
|
11
|
+
export async function recordQuota(rt, id, attribution, observation) {
|
|
12
|
+
const { ctx } = rt;
|
|
13
|
+
const locks = new LockStack(ctx.lockDefaults, ctx.lockEnv);
|
|
14
|
+
const progress = { writes: 0 };
|
|
15
|
+
try {
|
|
16
|
+
if (!isCredentialEpoch(attribution?.credentialEpoch))
|
|
17
|
+
throw refusal('pull', id, 'invalid-input', 'the credential epoch the reading was issued for must be a positive safe integer');
|
|
18
|
+
await withTransaction(ctx, locks, progress, { operation: 'pull', rowId: id }, async (tx) => {
|
|
19
|
+
tx.assertNotStaged(id);
|
|
20
|
+
const row = tx.row(id);
|
|
21
|
+
if (!row)
|
|
22
|
+
throw unknownRow('pull', id);
|
|
23
|
+
if (row.invalid)
|
|
24
|
+
throw refusal('pull', id, 'invalid-row', `row ${id} is invalid`);
|
|
25
|
+
// A reading belongs to one (epoch, identity, credential). A row
|
|
26
|
+
// holding no credential, or torn between the writes of a replace,
|
|
27
|
+
// has no such triple on disk, so no reading is recorded for it.
|
|
28
|
+
if (!row.credential)
|
|
29
|
+
throw refusal('pull', id, 'no-credential', `row ${id} holds no credential`);
|
|
30
|
+
requireBound('pull', row);
|
|
31
|
+
const entry = tx.entry(id);
|
|
32
|
+
if (row.torn ||
|
|
33
|
+
!entry ||
|
|
34
|
+
entry.credentialEpoch !== attribution.credentialEpoch ||
|
|
35
|
+
row.identity !== attribution.identity)
|
|
36
|
+
throw new PoolOperationError({
|
|
37
|
+
operation: 'pull',
|
|
38
|
+
rowId: id,
|
|
39
|
+
phase: 'pull',
|
|
40
|
+
retryable: true,
|
|
41
|
+
kind: 'attribution',
|
|
42
|
+
message: `quota for ${id} was issued for a credential the row no longer holds`,
|
|
43
|
+
});
|
|
44
|
+
const merged = ctx.codec.merge(entry.quota, observation);
|
|
45
|
+
if (!ctx.codec.validate(merged))
|
|
46
|
+
throw refusal('pull', id, 'invalid-quota', 'the quota codec rejected the merged map');
|
|
47
|
+
tx.setEntry(id, { ...entry, quota: merged, needsFirstReading: false });
|
|
48
|
+
await tx.commitConfig();
|
|
49
|
+
},
|
|
50
|
+
// Recording a reading never completes a torn row: the fence above
|
|
51
|
+
// refuses it, and the row's own next write completes it.
|
|
52
|
+
{ completeTorn: false });
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
throw toFailure(error, 'pull', id, progress);
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
await locks.releaseAll();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { StoredCredential } from './schema.js';
|
|
2
|
+
/** Every library operation that can fail, as named in the failure value. */
|
|
3
|
+
export type PoolOperation = 'initialize' | 'add' | 'replace' | 'rotate' | 'disable' | 'enable' | 'remove' | 'reorder' | 'updateSettings' | 'recordIdentity' | 'updateProviderState' | 'refresh' | 'pull' | 'publishRoster';
|
|
4
|
+
/**
|
|
5
|
+
* How far an operation got before it failed.
|
|
6
|
+
*
|
|
7
|
+
* `before-first-write`: nothing was written; both files are as they were.
|
|
8
|
+
* `after-first-write`: the operation's first file write landed and a later one
|
|
9
|
+
* did not; what that first write left is on disk and is never rolled back
|
|
10
|
+
* (add: a state entry no roster row names, which no reader loads; replace:
|
|
11
|
+
* the new credential stamped ahead of the config, which readers show as a
|
|
12
|
+
* torn row and the next store write on it completes; rotate: the rotated
|
|
13
|
+
* credential beside the old per-row entry). `pull`: a quota pull, or the
|
|
14
|
+
* recording of its result, failed.
|
|
15
|
+
*/
|
|
16
|
+
export type PoolFailurePhase = 'before-first-write' | 'after-first-write' | 'pull';
|
|
17
|
+
/**
|
|
18
|
+
* Why an operation failed. `lock-contention` and `lock-ownership` are the two
|
|
19
|
+
* lock outcomes (a wait that ran out, and a lease found lost); the rest are
|
|
20
|
+
* refusals and failures of the operation itself.
|
|
21
|
+
*/
|
|
22
|
+
export type PoolFailureKind = 'lock-contention' | 'lock-ownership' | 'pending-migration' | 'load-error' | 'snapshot-contended' | 'publication-sync' | 'publication-incomplete' | 'unknown-row' | 'invalid-row' | 'invalid-input' | 'id-exists' | 'id-removed' | 'type-mismatch' | 'no-credential' | 'row-disabled' | 'row-protected' | 'row-staged' | 'credential-exists' | 'publication-mismatch' | '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';
|
|
23
|
+
/**
|
|
24
|
+
* The single failure value of every store operation. `committed` is present
|
|
25
|
+
* only when the operation had already written a credential to the state file
|
|
26
|
+
* before it failed (a partial rotation or refresh): it is the credential now
|
|
27
|
+
* on disk, so a caller never has to re-read the files to learn it.
|
|
28
|
+
*/
|
|
29
|
+
export declare class PoolOperationError extends Error {
|
|
30
|
+
readonly operation: PoolOperation;
|
|
31
|
+
readonly rowId: string | undefined;
|
|
32
|
+
readonly phase: PoolFailurePhase;
|
|
33
|
+
readonly retryable: boolean;
|
|
34
|
+
readonly kind: PoolFailureKind;
|
|
35
|
+
readonly committed: StoredCredential | undefined;
|
|
36
|
+
constructor(details: {
|
|
37
|
+
operation: PoolOperation;
|
|
38
|
+
rowId?: string;
|
|
39
|
+
phase: PoolFailurePhase;
|
|
40
|
+
retryable: boolean;
|
|
41
|
+
kind: PoolFailureKind;
|
|
42
|
+
committed?: StoredCredential;
|
|
43
|
+
message?: string;
|
|
44
|
+
cause?: unknown;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Thrown when a row operation or a refresh is called from inside a hook of a
|
|
49
|
+
* lock-holding operation (or from any continuation created inside one). It is
|
|
50
|
+
* thrown before any lock is taken or waited for.
|
|
51
|
+
*/
|
|
52
|
+
export declare class PoolReentryError extends Error {
|
|
53
|
+
readonly operation: PoolOperation;
|
|
54
|
+
constructor(operation: PoolOperation);
|
|
55
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single failure value of every store operation. `committed` is present
|
|
3
|
+
* only when the operation had already written a credential to the state file
|
|
4
|
+
* before it failed (a partial rotation or refresh): it is the credential now
|
|
5
|
+
* on disk, so a caller never has to re-read the files to learn it.
|
|
6
|
+
*/
|
|
7
|
+
export class PoolOperationError extends Error {
|
|
8
|
+
operation;
|
|
9
|
+
rowId;
|
|
10
|
+
phase;
|
|
11
|
+
retryable;
|
|
12
|
+
kind;
|
|
13
|
+
committed;
|
|
14
|
+
constructor(details) {
|
|
15
|
+
super(details.message ??
|
|
16
|
+
`${details.operation} failed (${details.kind}, ${details.phase})`, details.cause === undefined ? undefined : { cause: details.cause });
|
|
17
|
+
this.name = 'PoolOperationError';
|
|
18
|
+
this.operation = details.operation;
|
|
19
|
+
this.rowId = details.rowId;
|
|
20
|
+
this.phase = details.phase;
|
|
21
|
+
this.retryable = details.retryable;
|
|
22
|
+
this.kind = details.kind;
|
|
23
|
+
this.committed = details.committed;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Thrown when a row operation or a refresh is called from inside a hook of a
|
|
28
|
+
* lock-holding operation (or from any continuation created inside one). It is
|
|
29
|
+
* thrown before any lock is taken or waited for.
|
|
30
|
+
*/
|
|
31
|
+
export class PoolReentryError extends Error {
|
|
32
|
+
operation;
|
|
33
|
+
constructor(operation) {
|
|
34
|
+
super(`${operation} was called from inside a store hook; hand it to the caller's continuation instead`);
|
|
35
|
+
this.name = 'PoolReentryError';
|
|
36
|
+
this.operation = operation;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type PoolOperation } from './errors.js';
|
|
2
|
+
/** Refuses a row operation or refresh called from inside a hook. */
|
|
3
|
+
export declare function assertNotInsideHook(operation: PoolOperation): void;
|
|
4
|
+
export declare function runInsideHook<T>(operation: PoolOperation, fn: () => Promise<T> | T): Promise<T>;
|
|
5
|
+
export interface PoolLogger {
|
|
6
|
+
warn(message: string, data?: unknown): void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Runs a failure hook. A hook that throws never replaces the failure it was
|
|
10
|
+
* handed: its exception is logged and discarded.
|
|
11
|
+
*/
|
|
12
|
+
export declare function callFailureHook<E, R extends string | undefined>(operation: PoolOperation, hook: ((rowId: R, error: E) => void | Promise<void>) | undefined, rowId: R, error: E, logger: PoolLogger | undefined): Promise<void>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
+
import { PoolReentryError } from './errors.js';
|
|
3
|
+
/**
|
|
4
|
+
* Set while a hook of a lock-holding operation runs. Async context is
|
|
5
|
+
* inherited by every timer, promise and continuation created inside the hook,
|
|
6
|
+
* so work a hook schedules is inside the guarded region too.
|
|
7
|
+
*/
|
|
8
|
+
const insideHook = new AsyncLocalStorage();
|
|
9
|
+
/** Refuses a row operation or refresh called from inside a hook. */
|
|
10
|
+
export function assertNotInsideHook(operation) {
|
|
11
|
+
if (insideHook.getStore() !== undefined)
|
|
12
|
+
throw new PoolReentryError(operation);
|
|
13
|
+
}
|
|
14
|
+
export function runInsideHook(operation, fn) {
|
|
15
|
+
return insideHook.run(operation, async () => await fn());
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Runs a failure hook. A hook that throws never replaces the failure it was
|
|
19
|
+
* handed: its exception is logged and discarded.
|
|
20
|
+
*/
|
|
21
|
+
export async function callFailureHook(operation, hook, rowId, error, logger) {
|
|
22
|
+
if (!hook)
|
|
23
|
+
return;
|
|
24
|
+
try {
|
|
25
|
+
await runInsideHook(operation, () => hook(rowId, error));
|
|
26
|
+
}
|
|
27
|
+
catch (hookError) {
|
|
28
|
+
logger?.warn('store failure hook threw; the original failure stands', {
|
|
29
|
+
operation,
|
|
30
|
+
rowId,
|
|
31
|
+
error: hookError instanceof Error ? hookError.message : String(hookError),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { PoolRow } from './schema.js';
|
|
2
|
+
/**
|
|
3
|
+
* What the identity rules edit: a transaction, or a config being completed
|
|
4
|
+
* in memory.
|
|
5
|
+
*/
|
|
6
|
+
export interface RowEditor {
|
|
7
|
+
rows(): PoolRow[];
|
|
8
|
+
rosterRow(id: string): Record<string, unknown> | undefined;
|
|
9
|
+
entry(id: string): Record<string, unknown> | undefined;
|
|
10
|
+
setEntry(id: string, entry: Record<string, unknown>): void;
|
|
11
|
+
}
|
|
12
|
+
/** Prefix of a refresh quarantine reason, followed by JSON of the expected and returned identities. */
|
|
13
|
+
export declare const IDENTITY_CONTRADICTED_REASON_PREFIX = "identity-contradicted: ";
|
|
14
|
+
/** The reason recorded on a row disabled because an earlier row is the same account. */
|
|
15
|
+
export declare const DUPLICATE_IDENTITY_REASON = "duplicate-identity";
|
|
16
|
+
/**
|
|
17
|
+
* Enabled OAuth rows holding a credential whose wire identity is not yet
|
|
18
|
+
* known. API-key rows and disabled rows never count.
|
|
19
|
+
*/
|
|
20
|
+
export declare function countUnknownIdentityRows(rows: readonly PoolRow[]): number;
|
|
21
|
+
/**
|
|
22
|
+
* Marks a row disabled with a reason: `enabled: false` in the roster row,
|
|
23
|
+
* which older readers honour, and the reason in the per-row entry. A row
|
|
24
|
+
* without an entry gets one at epoch 1. Nothing is ever deleted.
|
|
25
|
+
*/
|
|
26
|
+
export declare function disableIn(tx: RowEditor, id: string, reason: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Marks a row enabled: `enabled: true` in the roster row and no
|
|
29
|
+
* `disabledReason` in its entry. A row without an entry is not given one.
|
|
30
|
+
*/
|
|
31
|
+
export declare function enableIn(tx: RowEditor, id: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* Two enabled OAuth rows with one wire identity are the same account: the
|
|
34
|
+
* earlier row in roster order stays enabled and every later one is disabled
|
|
35
|
+
* with a reason. Returns the ids it disabled.
|
|
36
|
+
*/
|
|
37
|
+
export declare function disableIdentityDuplicates(tx: RowEditor, identity: string): string[];
|
|
38
|
+
/** Records a row's wire identity in its roster row, then applies dedupe. */
|
|
39
|
+
export declare function recordIdentityIn(tx: RowEditor, id: string, identity: string): string[];
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/** Prefix of a refresh quarantine reason, followed by JSON of the expected and returned identities. */
|
|
2
|
+
export const IDENTITY_CONTRADICTED_REASON_PREFIX = 'identity-contradicted: ';
|
|
3
|
+
/** The reason recorded on a row disabled because an earlier row is the same account. */
|
|
4
|
+
export const DUPLICATE_IDENTITY_REASON = 'duplicate-identity';
|
|
5
|
+
/**
|
|
6
|
+
* Enabled OAuth rows holding a credential whose wire identity is not yet
|
|
7
|
+
* known. API-key rows and disabled rows never count.
|
|
8
|
+
*/
|
|
9
|
+
export function countUnknownIdentityRows(rows) {
|
|
10
|
+
return rows.filter((row) => row.invalid === undefined &&
|
|
11
|
+
!row.staged &&
|
|
12
|
+
row.type === 'oauth' &&
|
|
13
|
+
row.enabled &&
|
|
14
|
+
row.credential !== undefined &&
|
|
15
|
+
row.identity === undefined).length;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Marks a row disabled with a reason: `enabled: false` in the roster row,
|
|
19
|
+
* which older readers honour, and the reason in the per-row entry. A row
|
|
20
|
+
* without an entry gets one at epoch 1. Nothing is ever deleted.
|
|
21
|
+
*/
|
|
22
|
+
export function disableIn(tx, id, reason) {
|
|
23
|
+
const raw = tx.rosterRow(id);
|
|
24
|
+
if (!raw)
|
|
25
|
+
return;
|
|
26
|
+
raw.enabled = false;
|
|
27
|
+
const entry = tx.entry(id) ?? { credentialEpoch: 1, needsFirstReading: true };
|
|
28
|
+
// A routine disable must not erase the evidence needed to refuse enable.
|
|
29
|
+
const quarantined = typeof entry.disabledReason === 'string' &&
|
|
30
|
+
entry.disabledReason.startsWith(IDENTITY_CONTRADICTED_REASON_PREFIX);
|
|
31
|
+
tx.setEntry(id, {
|
|
32
|
+
...entry,
|
|
33
|
+
disabledReason: quarantined ? entry.disabledReason : reason,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Marks a row enabled: `enabled: true` in the roster row and no
|
|
38
|
+
* `disabledReason` in its entry. A row without an entry is not given one.
|
|
39
|
+
*/
|
|
40
|
+
export function enableIn(tx, id) {
|
|
41
|
+
const raw = tx.rosterRow(id);
|
|
42
|
+
if (!raw)
|
|
43
|
+
return;
|
|
44
|
+
raw.enabled = true;
|
|
45
|
+
const entry = tx.entry(id);
|
|
46
|
+
if (entry && 'disabledReason' in entry) {
|
|
47
|
+
const next = { ...entry };
|
|
48
|
+
delete next.disabledReason;
|
|
49
|
+
tx.setEntry(id, next);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Two enabled OAuth rows with one wire identity are the same account: the
|
|
54
|
+
* earlier row in roster order stays enabled and every later one is disabled
|
|
55
|
+
* with a reason. Returns the ids it disabled.
|
|
56
|
+
*/
|
|
57
|
+
export function disableIdentityDuplicates(tx, identity) {
|
|
58
|
+
const holders = tx
|
|
59
|
+
.rows()
|
|
60
|
+
.filter((row) => row.invalid === undefined &&
|
|
61
|
+
!row.staged &&
|
|
62
|
+
row.type === 'oauth' &&
|
|
63
|
+
row.enabled &&
|
|
64
|
+
row.identity === identity);
|
|
65
|
+
const disabled = [];
|
|
66
|
+
for (const row of holders.slice(1)) {
|
|
67
|
+
disableIn(tx, row.id, DUPLICATE_IDENTITY_REASON);
|
|
68
|
+
disabled.push(row.id);
|
|
69
|
+
}
|
|
70
|
+
return disabled;
|
|
71
|
+
}
|
|
72
|
+
/** Records a row's wire identity in its roster row, then applies dedupe. */
|
|
73
|
+
export function recordIdentityIn(tx, id, identity) {
|
|
74
|
+
const raw = tx.rosterRow(id);
|
|
75
|
+
if (!raw)
|
|
76
|
+
return [];
|
|
77
|
+
raw.accountId = identity;
|
|
78
|
+
return disableIdentityDuplicates(tx, identity);
|
|
79
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type { Attribution } from './attribution.js';
|
|
2
|
+
export type { PoolFailureKind, PoolFailurePhase, PoolOperation, } from './errors.js';
|
|
3
|
+
export { PoolOperationError, PoolReentryError } from './errors.js';
|
|
4
|
+
export type { PoolLogger } from './hooks.js';
|
|
5
|
+
export { countUnknownIdentityRows, DUPLICATE_IDENTITY_REASON, } from './identity.js';
|
|
6
|
+
export type { HoldPoint, InitializeOutcome, WriteStep } from './mutate.js';
|
|
7
|
+
export type { OpenPoolStoreOptions, PoolLoad, PoolStore, } from './pool.js';
|
|
8
|
+
export { openPoolStore } from './pool.js';
|
|
9
|
+
export type { ProviderStateMutator, RowTransitionMutator, UpdateProviderStateResult, } from './provider-state.js';
|
|
10
|
+
export { DECLINE_TRANSITION } from './provider-state.js';
|
|
11
|
+
export type { PublicationReceipt, PublishOptions, PublishPlan, PublishResult, } from './publication.js';
|
|
12
|
+
export type { PullHook, PullRequest } from './pull.js';
|
|
13
|
+
export type { ProviderRefresh, ProviderRefreshResult, RefreshOptions, RefreshOutcome, } from './refresh.js';
|
|
14
|
+
export type { LockEvent, PoolLockOptions, PoolLockSpec, } from './refresh-lock.js';
|
|
15
|
+
export { POOL_LOCK_DEFAULTS } from './refresh-lock.js';
|
|
16
|
+
export type { AddInput, AddOptions, AddResult, CredentialWriteInput, FailureHook, ProtectFn, ProtectView, RemoveOptions, RemoveResult, RemoveView, ReorderOptions, ReorderResult, RowOperationOptions, RowProjection, RowToggleOptions, RowTransitionOptions, RowTransitionResult, RowWriteOptions, } from './rows.js';
|
|
17
|
+
export type { PullReason } from './runtime.js';
|
|
18
|
+
export type { ApiKeyCredential, CredentialStampStatus, OAuthCredential, PoolCredential, PoolRow, ProviderStateCodec, ProviderStateDrop, ProviderStateReplacement, QuotaCodec, RotateCredential, StoredCredential, } from './schema.js';
|
|
19
|
+
export { fingerprintOf, LEGACY_STORE_VERSION, POOL_KEY, POOL_ROWS_KEY, POOL_SCHEMA_VERSION, PROVIDER_STATE_KEY, REFRESH_STAMP_TOLERANCE_MS, rowLockKey, } from './schema.js';
|
|
20
|
+
export type { PoolSettings, SettingsMutator, SettingsRead, UpdateSettingsOptions, UpdateSettingsResult, } from './settings.js';
|
|
21
|
+
export { POOL_OWNED_KEYS } from './settings.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { PoolOperationError, PoolReentryError } from './errors.js';
|
|
2
|
+
export { countUnknownIdentityRows, DUPLICATE_IDENTITY_REASON, } from './identity.js';
|
|
3
|
+
export { openPoolStore } from './pool.js';
|
|
4
|
+
export { DECLINE_TRANSITION } from './provider-state.js';
|
|
5
|
+
export { POOL_LOCK_DEFAULTS } from './refresh-lock.js';
|
|
6
|
+
export { fingerprintOf, LEGACY_STORE_VERSION, POOL_KEY, POOL_ROWS_KEY, POOL_SCHEMA_VERSION, PROVIDER_STATE_KEY, REFRESH_STAMP_TOLERANCE_MS, rowLockKey, } from './schema.js';
|
|
7
|
+
export { POOL_OWNED_KEYS } from './settings.js';
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { type PoolFailurePhase, type PoolOperation, PoolOperationError } from './errors.js';
|
|
2
|
+
import { type PoolLogger } from './hooks.js';
|
|
3
|
+
import { type LockEnvironment, LockStack, type PoolLockOptions, type PoolLockSpec } from './refresh-lock.js';
|
|
4
|
+
import { type PoolRow, type ProviderStateCodec, type QuotaCodec, type StoredCredential } from './schema.js';
|
|
5
|
+
/** Named points on the write path, for crash and ownership injection. */
|
|
6
|
+
export type WriteStep = 'before-config-write' | 'after-config-write' | 'before-state-write' | 'after-state-write';
|
|
7
|
+
/** Awaitable pause points on the pull and refresh paths. */
|
|
8
|
+
export type HoldPoint = 'refresh-before-provider' | 'pull-before-request';
|
|
9
|
+
export interface StoreContext {
|
|
10
|
+
provider: string;
|
|
11
|
+
configPath: string;
|
|
12
|
+
statePath: string;
|
|
13
|
+
codec: QuotaCodec;
|
|
14
|
+
/** The provider-state codec; without one no row shows a provider state. */
|
|
15
|
+
providerState?: ProviderStateCodec;
|
|
16
|
+
now: () => number;
|
|
17
|
+
storeLocks: readonly PoolLockSpec[];
|
|
18
|
+
lockDefaults: PoolLockOptions;
|
|
19
|
+
lockEnv: LockEnvironment;
|
|
20
|
+
logger?: PoolLogger;
|
|
21
|
+
onStep?: (step: WriteStep, info: {
|
|
22
|
+
operation: PoolOperation;
|
|
23
|
+
rowId: string | undefined;
|
|
24
|
+
}) => void | Promise<void>;
|
|
25
|
+
hold?: (point: HoldPoint, rowId: string) => void | Promise<void>;
|
|
26
|
+
/** Ids whose per-row entry a library write dropped in this process. */
|
|
27
|
+
removedIds: Set<string>;
|
|
28
|
+
/**
|
|
29
|
+
* When true, rows whose credential stamp is not bound load `unbound` and
|
|
30
|
+
* the operations that use a credential refuse them (see
|
|
31
|
+
* `OpenPoolStoreOptions.requireCredentialStamps`).
|
|
32
|
+
*/
|
|
33
|
+
requireCredentialStamps?: boolean;
|
|
34
|
+
requireRemovedFingerprint?: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface Snapshot {
|
|
37
|
+
configExists: boolean;
|
|
38
|
+
stateExists: boolean;
|
|
39
|
+
config: Record<string, unknown>;
|
|
40
|
+
state: Record<string, unknown>;
|
|
41
|
+
rows: PoolRow[];
|
|
42
|
+
}
|
|
43
|
+
export type ReadResult = ({
|
|
44
|
+
status: 'ready';
|
|
45
|
+
} & Snapshot) | {
|
|
46
|
+
status: 'pending-migration';
|
|
47
|
+
config: Record<string, unknown>;
|
|
48
|
+
} | {
|
|
49
|
+
status: 'error';
|
|
50
|
+
file: 'config' | 'state';
|
|
51
|
+
reason: string;
|
|
52
|
+
kind?: 'snapshot-contended';
|
|
53
|
+
retryable?: true;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Validate config/state/config bytes without locks. Roster replacement writes
|
|
57
|
+
* config before deleting old state credentials. Re-read a changed config so an
|
|
58
|
+
* old roster cannot be paired with state from which its accounts were removed.
|
|
59
|
+
*/
|
|
60
|
+
export declare function readPool(ctx: StoreContext): Promise<ReadResult>;
|
|
61
|
+
/** The refusal for a pool that is not ready, as a failure value. */
|
|
62
|
+
export declare function notReadyError(result: Exclude<ReadResult, {
|
|
63
|
+
status: 'ready';
|
|
64
|
+
}>, operation: PoolOperation, rowId: string | undefined, phase?: PoolFailurePhase): PoolOperationError;
|
|
65
|
+
/** What an operation has written so far; decides the failure phase. */
|
|
66
|
+
export interface Progress {
|
|
67
|
+
writes: number;
|
|
68
|
+
/** The roster config was renamed into place, or its committed receipt was found. */
|
|
69
|
+
publicationDecided?: true;
|
|
70
|
+
/** The credential the operation's state write put on disk, once it has. */
|
|
71
|
+
committed?: StoredCredential;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* One locked read-modify-write. The store locks are pushed onto the caller's
|
|
75
|
+
* lock stack, so the ownership assertion before each write covers the outer
|
|
76
|
+
* row, provider-wide and extra locks as well; they are released when the
|
|
77
|
+
* transaction ends, whatever happens.
|
|
78
|
+
*/
|
|
79
|
+
export declare class Transaction {
|
|
80
|
+
private readonly ctx;
|
|
81
|
+
readonly snapshot: Snapshot;
|
|
82
|
+
private readonly locks;
|
|
83
|
+
private readonly progress;
|
|
84
|
+
readonly info: {
|
|
85
|
+
operation: PoolOperation;
|
|
86
|
+
rowId: string | undefined;
|
|
87
|
+
};
|
|
88
|
+
config: Record<string, unknown>;
|
|
89
|
+
state: Record<string, unknown>;
|
|
90
|
+
constructor(ctx: StoreContext, snapshot: Snapshot, locks: LockStack, progress: Progress, info: {
|
|
91
|
+
operation: PoolOperation;
|
|
92
|
+
rowId: string | undefined;
|
|
93
|
+
});
|
|
94
|
+
/**
|
|
95
|
+
* The rows as every reader loads them: a row torn between the writes of a
|
|
96
|
+
* replace is shown as that replace leaves it once completed (see
|
|
97
|
+
* `PoolRow.torn`).
|
|
98
|
+
*/
|
|
99
|
+
rows(): PoolRow[];
|
|
100
|
+
row(id: string): PoolRow | undefined;
|
|
101
|
+
/** Read the config marker, or an orphan's stamp; never use a caller's reservation. */
|
|
102
|
+
reservation(id: string): unknown;
|
|
103
|
+
assertNotStaged(id: string): void;
|
|
104
|
+
roster(): unknown[];
|
|
105
|
+
/** The first roster row with this id (the one the pool loads). */
|
|
106
|
+
rosterRow(id: string): Record<string, unknown> | undefined;
|
|
107
|
+
/**
|
|
108
|
+
* Drops every roster row carrying this id. The row's per-row entry goes with
|
|
109
|
+
* it on the next `commitConfig`, which drops entries for ids no longer in
|
|
110
|
+
* the roster. Returns how many roster rows were dropped.
|
|
111
|
+
*/
|
|
112
|
+
dropRosterRows(id: string): number;
|
|
113
|
+
entries(): Record<string, unknown>;
|
|
114
|
+
entry(id: string): Record<string, unknown> | undefined;
|
|
115
|
+
setEntry(id: string, entry: Record<string, unknown>): void;
|
|
116
|
+
/**
|
|
117
|
+
* Writes the config of every row torn between the writes of a replace, or
|
|
118
|
+
* of a write giving it its first identity, as that write would have left it
|
|
119
|
+
* (see `completeTornRows`), in one config
|
|
120
|
+
* write ahead of the operation's own. The write is counted apart from the
|
|
121
|
+
* operation's: it is setup, like a pull giving a row its entry, so a later
|
|
122
|
+
* refusal still reports `before-first-write`.
|
|
123
|
+
*/
|
|
124
|
+
completeTorn(): Promise<void>;
|
|
125
|
+
stateAccount(id: string): Record<string, unknown> | undefined;
|
|
126
|
+
/** Drops the row's credential and runtime fields from the state file's accounts. */
|
|
127
|
+
dropStateAccount(id: string): void;
|
|
128
|
+
setStateAccount(id: string, fields: Record<string, unknown>): void;
|
|
129
|
+
/**
|
|
130
|
+
* Writes the config: legacy `version: 1` and the legacy roster beside
|
|
131
|
+
* `commonAuthPool`, every other top-level key and every unrecognised pool
|
|
132
|
+
* key untouched. Entries for ids no longer in the roster are dropped here,
|
|
133
|
+
* and remembered so the id is not reused in this process. Every id the
|
|
134
|
+
* write drops (a roster row the files held when the transaction read them,
|
|
135
|
+
* or an entry left without one) has its epoch recorded in the config (see
|
|
136
|
+
* `retireEpochsIn`), which is what keeps a later `add` of the id, from any
|
|
137
|
+
* process, past every epoch an attribution could name.
|
|
138
|
+
*/
|
|
139
|
+
commitConfig(options?: {
|
|
140
|
+
counted?: boolean;
|
|
141
|
+
durable?: boolean;
|
|
142
|
+
publicationDecision?: boolean;
|
|
143
|
+
}): Promise<void>;
|
|
144
|
+
/** Writes the state: every unrecognised top-level and per-row key kept. */
|
|
145
|
+
commitState(committed?: StoredCredential, options?: {
|
|
146
|
+
durable?: boolean;
|
|
147
|
+
}): Promise<void>;
|
|
148
|
+
assertAll(): Promise<void>;
|
|
149
|
+
syncState(): Promise<void>;
|
|
150
|
+
markPublicationDecision(): void;
|
|
151
|
+
syncConfig(): Promise<void>;
|
|
152
|
+
private write;
|
|
153
|
+
}
|
|
154
|
+
/** What `initializePool` did. */
|
|
155
|
+
export type InitializeOutcome = 'initialized' | 'already-ready';
|
|
156
|
+
/**
|
|
157
|
+
* Adds the pool key to a config that holds a legacy roster without one, under
|
|
158
|
+
* the store-lock list, in one config write: `commonAuthPool` with the schema
|
|
159
|
+
* version and no row entries, the legacy roster and every other top-level key
|
|
160
|
+
* kept, except the keys named in `dropKeys`. The state file is not touched.
|
|
161
|
+
* This is the only write the store makes to a pending-migration config; it is
|
|
162
|
+
* where a plugin's migration starts, and every later row goes through the
|
|
163
|
+
* ordinary operations. A config that is already a pool is left alone; a load
|
|
164
|
+
* error refuses.
|
|
165
|
+
*/
|
|
166
|
+
export declare function initializePool(ctx: StoreContext, dropKeys: readonly string[]): Promise<InitializeOutcome>;
|
|
167
|
+
/**
|
|
168
|
+
* Runs `fn` under the store-lock list. The pool must be ready: a pending
|
|
169
|
+
* migration or a load error refuses before anything is written. Unless
|
|
170
|
+
* `completeTorn` is false, rows torn between the writes of a replace are
|
|
171
|
+
* completed first, so `fn` never sees one; the writes that only record
|
|
172
|
+
* readings or reorder the roster opt out and leave such rows as they are.
|
|
173
|
+
*/
|
|
174
|
+
export declare function withTransaction<T>(ctx: StoreContext, locks: LockStack, progress: Progress, info: {
|
|
175
|
+
operation: PoolOperation;
|
|
176
|
+
rowId: string | undefined;
|
|
177
|
+
}, fn: (tx: Transaction) => Promise<T>, options?: {
|
|
178
|
+
completeTorn?: boolean;
|
|
179
|
+
}): Promise<T>;
|
|
180
|
+
/** Maps anything thrown inside an operation onto the one failure value. */
|
|
181
|
+
export declare function toFailure(error: unknown, operation: PoolOperation, rowId: string | undefined, progress: Progress): PoolOperationError;
|
|
182
|
+
/**
|
|
183
|
+
* The frame every lock-holding operation runs in: failures are mapped onto
|
|
184
|
+
* the failure value, handed to the failure hook while the outer locks are
|
|
185
|
+
* still held (the store locks are already released), and rethrown; every
|
|
186
|
+
* lock is released afterwards. `rowId` is undefined for an operation that
|
|
187
|
+
* names no row (`reorder`).
|
|
188
|
+
*/
|
|
189
|
+
export declare function runOperation<T, R extends string | undefined = string>(ctx: StoreContext, operation: PoolOperation, rowId: R, onFailure: ((rowId: R, error: PoolOperationError) => void | Promise<void>) | undefined, body: (locks: LockStack, progress: Progress) => Promise<T>): Promise<T>;
|