@cortexkit/common-auth 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cachekeep/manager.d.ts +18 -6
- package/dist/cachekeep/manager.js +40 -10
- package/dist/claustrum/consumer.d.ts +13 -4
- package/dist/claustrum/consumer.js +11 -3
- package/dist/claustrum/custody.d.ts +47 -6
- package/dist/claustrum/custody.js +37 -7
- package/dist/claustrum/errors.d.ts +1 -1
- package/dist/claustrum/index.d.ts +3 -3
- package/dist/claustrum/index.js +2 -2
- package/dist/claustrum/interlock.d.ts +15 -17
- package/dist/claustrum/interlock.js +19 -26
- package/dist/claustrum/roster.d.ts +96 -6
- package/dist/claustrum/roster.js +209 -44
- package/dist/commands/builtins.d.ts +1 -1
- package/dist/commands/builtins.js +6 -1
- package/dist/commands/index.d.ts +2 -2
- package/dist/commands/index.js +1 -1
- package/dist/commands/menu.d.ts +8 -0
- package/dist/commands/menu.js +34 -13
- package/dist/commands/model.d.ts +9 -0
- package/dist/commands/seam.d.ts +40 -4
- package/dist/commands/seam.js +132 -19
- package/dist/dump/index.d.ts +94 -0
- package/dist/dump/index.js +236 -9
- package/dist/logger/engine.d.ts +52 -17
- package/dist/logger/engine.js +178 -135
- package/dist/logger/index.d.ts +2 -2
- package/dist/logger/index.js +1 -1
- package/dist/opencode2/install.d.ts +8 -3
- package/dist/opencode2/install.js +18 -9
- package/dist/opencode2/types.d.ts +22 -3
- package/dist/quota/projection.d.ts +11 -4
- package/dist/quota/projection.js +11 -4
- package/dist/routing/admission.js +3 -1
- package/dist/routing/index.d.ts +2 -2
- package/dist/routing/index.js +1 -1
- package/dist/routing/sticky.d.ts +19 -6
- package/dist/routing/sticky.js +34 -23
- package/dist/rpc/notifications.d.ts +20 -0
- package/dist/rpc/notifications.js +21 -0
- package/dist/rpc/rpc-server.d.ts +9 -1
- package/dist/rpc/rpc-server.js +8 -1
- package/dist/sidebar-file/index.d.ts +1 -1
- package/dist/sidebar-file/sidebar-file.d.ts +50 -2
- package/dist/sidebar-file/sidebar-file.js +92 -21
- package/dist/store/attribution.js +11 -2
- package/dist/store/errors.d.ts +6 -3
- package/dist/store/identity.d.ts +13 -4
- package/dist/store/mutate.d.ts +23 -3
- package/dist/store/mutate.js +43 -26
- package/dist/store/pool.d.ts +8 -1
- package/dist/store/pool.js +7 -2
- package/dist/store/rows.d.ts +17 -4
- package/dist/store/rows.js +82 -33
- package/dist/store/schema.d.ts +57 -4
- package/dist/store/schema.js +100 -7
- package/dist/store/torn.d.ts +29 -0
- package/dist/store/torn.js +113 -0
- package/package.json +1 -1
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type RowEditor } from './identity.js';
|
|
2
|
+
import { type CredentialBinding, type CredentialStamp, type PoolRow, type QuotaCodec } from './schema.js';
|
|
3
|
+
/** Stamps of rows torn between the two writes of a replace, by row id. */
|
|
4
|
+
export declare function tornStamps(config: Record<string, unknown>, state: Record<string, unknown>, codec: QuotaCodec): Map<string, CredentialStamp & {
|
|
5
|
+
binding: CredentialBinding;
|
|
6
|
+
}>;
|
|
7
|
+
/**
|
|
8
|
+
* The config half of a replacement: the row's entry moves to the new epoch,
|
|
9
|
+
* loses its quota and needs a first reading; its roster row gets the new
|
|
10
|
+
* identity (or loses the old one) and, for an API key, the new endpoint.
|
|
11
|
+
* Disabling later rows that share the new identity is left to the caller
|
|
12
|
+
* (`disableIdentityDuplicates`), so several rows can be bound first.
|
|
13
|
+
*/
|
|
14
|
+
export declare function bindReplacement(editor: RowEditor, id: string, credentialEpoch: number, binding: CredentialBinding): void;
|
|
15
|
+
/**
|
|
16
|
+
* The config with every torn row completed as its replace would have left
|
|
17
|
+
* it, and the ids completed. The config passed in is not modified; when
|
|
18
|
+
* nothing is torn it is returned as is.
|
|
19
|
+
*/
|
|
20
|
+
export declare function completeTornRows(config: Record<string, unknown>, state: Record<string, unknown>, codec: QuotaCodec): {
|
|
21
|
+
config: Record<string, unknown>;
|
|
22
|
+
torn: string[];
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* The rows every reader gets. A torn row is shown completed (the identity,
|
|
26
|
+
* endpoint and epoch its stamp names, beside the credential it stamps), is
|
|
27
|
+
* marked `torn` and is never a candidate; every other row is as on disk.
|
|
28
|
+
*/
|
|
29
|
+
export declare function loadRows(config: Record<string, unknown>, state: Record<string, unknown>, codec: QuotaCodec): PoolRow[];
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { disableIdentityDuplicates } from './identity.js';
|
|
2
|
+
import { buildRawRows, CREDENTIAL_STAMP_KEY, credentialDigest, entryIn, isRecord, parseStamp, rosterRowIn, setEntryIn, } from './schema.js';
|
|
3
|
+
/*
|
|
4
|
+
* A replace changes both files: the state file gets the new credential and
|
|
5
|
+
* the config gets the new epoch, identity or endpoint. It writes the state
|
|
6
|
+
* file first, stamping the credential with the epoch it belongs to and the
|
|
7
|
+
* binding (identity, endpoint) the config is about to get. A crash between
|
|
8
|
+
* the two writes therefore leaves a credential whose stamp is ahead of the
|
|
9
|
+
* config's epoch, and that is how every reader tells such a torn row from a
|
|
10
|
+
* whole one. The stamp holds everything the config write would have written,
|
|
11
|
+
* so a torn row is completed forward: readers are shown the completed row
|
|
12
|
+
* (never a candidate until it is on disk) and the next store write on it
|
|
13
|
+
* writes the config to match.
|
|
14
|
+
*
|
|
15
|
+
* A stamp counts only beside the credential it was written with (its digest
|
|
16
|
+
* matches): a writer that does not know about stamps may put another
|
|
17
|
+
* credential beside an old one, and that stamp then says nothing. A stamp at
|
|
18
|
+
* or behind the config's epoch is never torn: this store's own writes leave
|
|
19
|
+
* the state file ahead of the config, never behind it.
|
|
20
|
+
*/
|
|
21
|
+
/** Stamps of rows torn between the two writes of a replace, by row id. */
|
|
22
|
+
export function tornStamps(config, state, codec) {
|
|
23
|
+
const accounts = isRecord(state.accounts) ? state.accounts : {};
|
|
24
|
+
const torn = new Map();
|
|
25
|
+
for (const row of buildRawRows(config, state, codec)) {
|
|
26
|
+
if (row.invalid || !row.credential)
|
|
27
|
+
continue;
|
|
28
|
+
const account = Object.hasOwn(accounts, row.id)
|
|
29
|
+
? accounts[row.id]
|
|
30
|
+
: undefined;
|
|
31
|
+
if (!isRecord(account))
|
|
32
|
+
continue;
|
|
33
|
+
const stamp = parseStamp(account[CREDENTIAL_STAMP_KEY]);
|
|
34
|
+
if (!stamp?.binding)
|
|
35
|
+
continue;
|
|
36
|
+
if (stamp.digest !== credentialDigest(row.credential))
|
|
37
|
+
continue;
|
|
38
|
+
// A row without an entry is at epoch 1, as everywhere else.
|
|
39
|
+
if (stamp.credentialEpoch <= (row.credentialEpoch ?? 1))
|
|
40
|
+
continue;
|
|
41
|
+
torn.set(row.id, { ...stamp, binding: stamp.binding });
|
|
42
|
+
}
|
|
43
|
+
return torn;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The config half of a replacement: the row's entry moves to the new epoch,
|
|
47
|
+
* loses its quota and needs a first reading; its roster row gets the new
|
|
48
|
+
* identity (or loses the old one) and, for an API key, the new endpoint.
|
|
49
|
+
* Disabling later rows that share the new identity is left to the caller
|
|
50
|
+
* (`disableIdentityDuplicates`), so several rows can be bound first.
|
|
51
|
+
*/
|
|
52
|
+
export function bindReplacement(editor, id, credentialEpoch, binding) {
|
|
53
|
+
const entry = editor.entry(id) ?? {};
|
|
54
|
+
const next = {
|
|
55
|
+
...entry,
|
|
56
|
+
credentialEpoch,
|
|
57
|
+
needsFirstReading: true,
|
|
58
|
+
};
|
|
59
|
+
delete next.quota;
|
|
60
|
+
editor.setEntry(id, next);
|
|
61
|
+
const raw = editor.rosterRow(id);
|
|
62
|
+
if (!raw)
|
|
63
|
+
return;
|
|
64
|
+
if (binding.identity !== undefined)
|
|
65
|
+
raw.accountId = binding.identity;
|
|
66
|
+
else
|
|
67
|
+
delete raw.accountId;
|
|
68
|
+
if (binding.baseURL !== undefined)
|
|
69
|
+
raw.baseURL = binding.baseURL;
|
|
70
|
+
if (binding.authHeader !== undefined)
|
|
71
|
+
raw.authHeader = binding.authHeader;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The config with every torn row completed as its replace would have left
|
|
75
|
+
* it, and the ids completed. The config passed in is not modified; when
|
|
76
|
+
* nothing is torn it is returned as is.
|
|
77
|
+
*/
|
|
78
|
+
export function completeTornRows(config, state, codec) {
|
|
79
|
+
const stamps = tornStamps(config, state, codec);
|
|
80
|
+
if (stamps.size === 0)
|
|
81
|
+
return { config, torn: [] };
|
|
82
|
+
const next = structuredClone(config);
|
|
83
|
+
const editor = {
|
|
84
|
+
rows: () => buildRawRows(next, state, codec),
|
|
85
|
+
rosterRow: (id) => rosterRowIn(next, id),
|
|
86
|
+
entry: (id) => entryIn(next, id),
|
|
87
|
+
setEntry: (id, entry) => setEntryIn(next, id, entry),
|
|
88
|
+
};
|
|
89
|
+
for (const [id, stamp] of stamps)
|
|
90
|
+
bindReplacement(editor, id, stamp.credentialEpoch, stamp.binding);
|
|
91
|
+
for (const stamp of stamps.values())
|
|
92
|
+
if (stamp.binding.identity !== undefined)
|
|
93
|
+
disableIdentityDuplicates(editor, stamp.binding.identity);
|
|
94
|
+
return { config: next, torn: [...stamps.keys()] };
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* The rows every reader gets. A torn row is shown completed (the identity,
|
|
98
|
+
* endpoint and epoch its stamp names, beside the credential it stamps), is
|
|
99
|
+
* marked `torn` and is never a candidate; every other row is as on disk.
|
|
100
|
+
*/
|
|
101
|
+
export function loadRows(config, state, codec) {
|
|
102
|
+
const { config: whole, torn } = completeTornRows(config, state, codec);
|
|
103
|
+
const rows = buildRawRows(whole, state, codec);
|
|
104
|
+
if (torn.length === 0)
|
|
105
|
+
return rows;
|
|
106
|
+
for (const row of rows) {
|
|
107
|
+
if (!torn.includes(row.id))
|
|
108
|
+
continue;
|
|
109
|
+
row.torn = true;
|
|
110
|
+
row.candidate = false;
|
|
111
|
+
}
|
|
112
|
+
return rows;
|
|
113
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cortexkit/common-auth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Shared code for the CortexKit auth plugins: account pool, quota and routing, commands and auth menu, OpenCode 2 hooks, Claustrum custody, and plumbing (loopback RPC, file locks, logger, sidebar state, TUI preferences and build).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|