@jini-ai/core 0.4.0 → 0.4.2
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/CHANGELOG.md +11 -0
- package/README.md +18 -1
- package/dist/agent-tools.d.ts +1 -0
- package/dist/approval.d.ts +134 -0
- package/dist/approval.js +141 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/model-facing-tool-errors.d.ts +152 -0
- package/dist/model-facing-tool-errors.js +124 -0
- package/dist/native-regexp.d.ts +10 -0
- package/dist/native-regexp.js +2 -0
- package/dist/primitives/index.d.ts +2 -0
- package/dist/primitives/index.js +1 -0
- package/dist/primitives/sse.d.ts +60 -0
- package/dist/primitives/sse.js +122 -0
- package/dist/redact.js +4 -3
- package/dist/registration-kit.d.ts +47 -0
- package/dist/registration-kit.js +55 -0
- package/dist/settings/agent-tools.d.ts +10 -0
- package/dist/settings/agent-tools.js +204 -0
- package/dist/settings/agent-value-write-tools.d.ts +22 -0
- package/dist/settings/agent-value-write-tools.js +157 -0
- package/dist/settings/agent-writable-preferences.d.ts +67 -0
- package/dist/settings/agent-writable-preferences.js +132 -0
- package/dist/settings/agent-write-denylist.d.ts +19 -0
- package/dist/settings/agent-write-denylist.js +15 -0
- package/dist/settings/change-feed.d.ts +83 -0
- package/dist/settings/change-feed.js +61 -0
- package/dist/settings/definitions-dispatch.d.ts +56 -0
- package/dist/settings/definitions-dispatch.js +86 -0
- package/dist/settings/dictionaries/index.d.ts +48 -0
- package/dist/settings/dictionaries/index.js +69 -0
- package/dist/settings/dictionaries/settings-dialog.ar.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.ar.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.bn.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.bn.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.de.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.de.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.es.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.es.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.fa.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.fa.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.fr.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.fr.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.hi.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.hi.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.hu.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.hu.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.id.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.id.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.it.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.it.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.ja.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.ja.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.ko.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.ko.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.pl.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.pl.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.pt-BR.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.pt-BR.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.ru.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.ru.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.th.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.th.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.tr.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.tr.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.uk.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.uk.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.ur.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.ur.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.zh-CN.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.zh-CN.js +27 -0
- package/dist/settings/dictionaries/settings-dialog.zh-TW.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.zh-TW.js +27 -0
- package/dist/settings/ensure-definitions.d.ts +101 -0
- package/dist/settings/ensure-definitions.js +101 -0
- package/dist/settings/errors.d.ts +42 -0
- package/dist/settings/errors.js +46 -0
- package/dist/settings/express/cms-adapter.d.ts +20 -0
- package/dist/settings/express/cms-adapter.js +124 -0
- package/dist/settings/express/contracts.d.ts +135 -0
- package/dist/settings/express/contracts.js +2 -0
- package/dist/settings/express/http.d.ts +10 -0
- package/dist/settings/express/http.js +211 -0
- package/dist/settings/express/index.d.ts +5 -0
- package/dist/settings/express/index.js +4 -0
- package/dist/settings/express/shared.d.ts +68 -0
- package/dist/settings/express/shared.js +54 -0
- package/dist/settings/express/stream.d.ts +24 -0
- package/dist/settings/express/stream.js +147 -0
- package/dist/settings/index.d.ts +40 -0
- package/dist/settings/index.js +37 -0
- package/dist/settings/ports.d.ts +118 -0
- package/dist/settings/ports.js +2 -0
- package/dist/settings/principal-lookup.d.ts +9 -0
- package/dist/settings/principal-lookup.js +2 -0
- package/dist/settings/purge-service.d.ts +54 -0
- package/dist/settings/purge-service.js +106 -0
- package/dist/settings/repo.memory.d.ts +119 -0
- package/dist/settings/repo.memory.js +199 -0
- package/dist/settings/settings.d.ts +139 -0
- package/dist/settings/settings.js +259 -0
- package/dist/settings/tool-registrations.d.ts +54 -0
- package/dist/settings/tool-registrations.js +250 -0
- package/dist/settings/types.d.ts +125 -0
- package/dist/settings/types.js +3 -0
- package/dist/settings/ui-tab-definitions.d.ts +41 -0
- package/dist/settings/ui-tab-definitions.js +148 -0
- package/dist/settings/write-service.d.ts +320 -0
- package/dist/settings/write-service.js +683 -0
- package/dist/surface-exchanges.d.ts +209 -0
- package/dist/surface-exchanges.js +55 -0
- package/dist/tool-metadata.d.ts +71 -0
- package/dist/tool-metadata.js +56 -0
- package/dist/tool-permissions.d.ts +76 -0
- package/dist/tool-permissions.js +57 -0
- package/dist/tool-registry.d.ts +3 -0
- package/package.json +62 -4
- package/dist/internal.d.ts +0 -41
- package/dist/internal.js +0 -39
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import type { Clock, IdGenerator, JsonValue, UUID } from "../primitives/index.js";
|
|
2
|
+
import type { SettingsPrincipalLookupPort } from "./principal-lookup.js";
|
|
3
|
+
import type { SettingsRepoPort } from "./ports.js";
|
|
4
|
+
import { type DefinitionInput } from "./settings.js";
|
|
5
|
+
import { type SettingScope, type SettingValueSchema } from "./types.js";
|
|
6
|
+
/**
|
|
7
|
+
* @file `SettingsWriteService` — the single write chokepoint.
|
|
8
|
+
*
|
|
9
|
+
* Purpose:
|
|
10
|
+
* The ONLY value/definition-mutation path. Repo write methods
|
|
11
|
+
* (`saveDefinition`/`save*Value`/`appendRevision`/`delete*Value`) must never
|
|
12
|
+
* be called from outside this file (Code Review enforces this as a file-
|
|
13
|
+
* boundary check).
|
|
14
|
+
*
|
|
15
|
+
* Every export here: `authorize` first (fail-closed) -> validate ->
|
|
16
|
+
* write value/definition row + revision in one transaction.
|
|
17
|
+
*
|
|
18
|
+
* `deriveRequiredPermission` is the sole source of truth for the self-vs-
|
|
19
|
+
* other permission rule (behavior.spec.md §1.3) — closes Red-Team.
|
|
20
|
+
* target-principal checks use a host-supplied active-principal lookup over core Principal;
|
|
21
|
+
* identity and membership policy remain at the host boundary.
|
|
22
|
+
* See docs/decisions/DR-003-settings-ledger-invariants.md.
|
|
23
|
+
*/
|
|
24
|
+
/** Matches `core/commands/command.ts`'s `AuthorizeFn` shape structurally — no import, kept decoupled. */
|
|
25
|
+
export type AuthorizeFn = (params: {
|
|
26
|
+
principalId: UUID;
|
|
27
|
+
permission: string;
|
|
28
|
+
workspaceId: UUID;
|
|
29
|
+
entityType?: string;
|
|
30
|
+
entityId?: UUID;
|
|
31
|
+
}) => Promise<{
|
|
32
|
+
allowed: boolean;
|
|
33
|
+
reason: string;
|
|
34
|
+
}>;
|
|
35
|
+
export interface SettingsWriteServiceDeps {
|
|
36
|
+
repo: SettingsRepoPort;
|
|
37
|
+
clock: Clock;
|
|
38
|
+
ids: IdGenerator;
|
|
39
|
+
authorize: AuthorizeFn;
|
|
40
|
+
/** Host lookup must hide disabled and out-of-workspace principals. See docs/decisions/DR-003-settings-ledger-invariants.md. */
|
|
41
|
+
principals: SettingsPrincipalLookupPort;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* behavior.spec.md §1.3 / `[internal-invariant]` — the self-vs-other
|
|
45
|
+
* permission derivation. `targetPrincipalId` omitted or equal to the caller
|
|
46
|
+
* -> `settings.user.self.write`; any other principal -> `settings.user.write`.
|
|
47
|
+
* A divergence between this function and any other implementation of the
|
|
48
|
+
* rule is a fail-open authorization bug (Red-Team ) — this is the only
|
|
49
|
+
* place the rule may be encoded.
|
|
50
|
+
*
|
|
51
|
+
* @complexity O(1), pure.
|
|
52
|
+
* @overallScore 100
|
|
53
|
+
* See docs/decisions/DR-003-settings-ledger-invariants.md.
|
|
54
|
+
*/
|
|
55
|
+
export declare function deriveRequiredPermission(input: {
|
|
56
|
+
scope: SettingScope;
|
|
57
|
+
targetPrincipalId?: UUID | undefined;
|
|
58
|
+
callerPrincipalId: UUID;
|
|
59
|
+
}): string;
|
|
60
|
+
export interface RegisterDefinitionsRequired {
|
|
61
|
+
deps: SettingsWriteServiceDeps;
|
|
62
|
+
input: {
|
|
63
|
+
definitions: DefinitionInput[];
|
|
64
|
+
callerPrincipalId: UUID;
|
|
65
|
+
/** The workspace the caller is authorizing in (always required — even platform-def registration is authorized within a workspace context). */
|
|
66
|
+
authWorkspaceId: UUID;
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/** chokepoint write: authorize `settings.definitions.manage` -> validate -> write + revision, one per definition, each its own tx. See docs/decisions/DR-003-settings-ledger-invariants.md. */
|
|
70
|
+
export declare function registerDefinitions(required: RegisterDefinitionsRequired): Promise<{
|
|
71
|
+
registered: string[];
|
|
72
|
+
}>;
|
|
73
|
+
export interface SetValueRequired {
|
|
74
|
+
deps: SettingsWriteServiceDeps;
|
|
75
|
+
input: {
|
|
76
|
+
namespace: string;
|
|
77
|
+
key: string;
|
|
78
|
+
scope: SettingScope;
|
|
79
|
+
value: JsonValue;
|
|
80
|
+
workspaceId?: UUID | undefined;
|
|
81
|
+
principalId?: UUID | undefined;
|
|
82
|
+
callerPrincipalId: UUID;
|
|
83
|
+
/**
|
|
84
|
+
* The ambient workspace to authorize the caller's grant in. Optional and
|
|
85
|
+
* additive: when omitted, falls back to `input.workspaceId ??
|
|
86
|
+
* input.callerPrincipalId`. Callers that DO have a real ambient workspace
|
|
87
|
+
* (every HTTP route in a single-workspace host) should pass it
|
|
88
|
+
* explicitly: for `scope=global` (no `workspaceId`), falling back to
|
|
89
|
+
* `callerPrincipalId` as a stand-in "workspace" id is nonsensical against
|
|
90
|
+
* the real `authorize()` (identity's own authorize looks the principal up
|
|
91
|
+
* by `{workspaceId, id}` — a bogus workspaceId means `findById` returns
|
|
92
|
+
* null and every request is denied `principal_disabled`, including the
|
|
93
|
+
* wildcard-owner).
|
|
94
|
+
*/
|
|
95
|
+
authWorkspaceId?: UUID | undefined;
|
|
96
|
+
/**
|
|
97
|
+
* `deriveRequiredPermission` unconditionally derives `settings.workspace.write` for
|
|
98
|
+
* `scope: "workspace"` — a caller that already authorized a narrower, domain-specific
|
|
99
|
+
* permission at its own route layer (e.g. a comments module's `comments.configure`, an SEO
|
|
100
|
+
* module's `admin.seo.manage`) still hits this chokepoint's generic `settings.workspace.write`
|
|
101
|
+
* check and gets a masked 500 if it lacks that broader grant, even though its own domain
|
|
102
|
+
* permission is exactly what the feature's admin UI advertises as sufficient. Optional and
|
|
103
|
+
* additive: omitted, behavior is unchanged (every pre-existing caller still gets the
|
|
104
|
+
* scope-derived permission). When a domain-settings module supplies this, the chokepoint
|
|
105
|
+
* authorizes THIS permission instead of the scope-derived one — still a mandatory
|
|
106
|
+
* `authorize` call before any write ( fail-closed discipline is not relaxed, only
|
|
107
|
+
* which permission string is checked).
|
|
108
|
+
* See docs/decisions/DR-003-settings-ledger-invariants.md.
|
|
109
|
+
*/
|
|
110
|
+
requiredPermissionOverride?: string | undefined;
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/** chokepoint write: authorize -> validate -> value + revision, same tx. See docs/decisions/DR-003-settings-ledger-invariants.md. */
|
|
114
|
+
export declare function set(required: SetValueRequired): Promise<{
|
|
115
|
+
value: JsonValue;
|
|
116
|
+
revisionSeq: number;
|
|
117
|
+
}>;
|
|
118
|
+
export interface ClearValueRequired {
|
|
119
|
+
deps: SettingsWriteServiceDeps;
|
|
120
|
+
input: {
|
|
121
|
+
namespace: string;
|
|
122
|
+
key: string;
|
|
123
|
+
scope: SettingScope;
|
|
124
|
+
workspaceId?: UUID | undefined;
|
|
125
|
+
principalId?: UUID | undefined;
|
|
126
|
+
callerPrincipalId: UUID;
|
|
127
|
+
/** Set by `resetNamespace` when looping `clear` in its own reset-authorized context — bypasses the inner authorize re-check, still writes a normal revision. See docs/decisions/DR-003-settings-ledger-invariants.md. */
|
|
128
|
+
skipAuthorize?: boolean | undefined;
|
|
129
|
+
/** Set by a caller that has ALREADY opened a transaction around this write —
|
|
130
|
+
* see `resetNamespace`. Explicit rather than an ambient depth counter,
|
|
131
|
+
* because an ambient one cannot tell a genuine nesting from a concurrent
|
|
132
|
+
* unrelated transaction and silently merges the two. */
|
|
133
|
+
skipTransaction?: boolean | undefined;
|
|
134
|
+
/** See `SetValueRequired.input.authWorkspaceId`'s doc. Optional/additive. */
|
|
135
|
+
authWorkspaceId?: UUID | undefined;
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/** chokepoint write: authorize -> value + revision (state='cleared'), same tx. See docs/decisions/DR-003-settings-ledger-invariants.md. */
|
|
139
|
+
export declare function clear(required: ClearValueRequired): Promise<{
|
|
140
|
+
revisionSeq: number;
|
|
141
|
+
}>;
|
|
142
|
+
export interface ResetNamespaceRequired {
|
|
143
|
+
deps: SettingsWriteServiceDeps;
|
|
144
|
+
input: {
|
|
145
|
+
namespace: string;
|
|
146
|
+
scope: Exclude<SettingScope, never>;
|
|
147
|
+
workspaceId?: UUID | undefined;
|
|
148
|
+
principalId?: UUID | undefined;
|
|
149
|
+
callerPrincipalId: UUID;
|
|
150
|
+
/** See `SetValueRequired.input.authWorkspaceId`'s doc. Optional/additive. */
|
|
151
|
+
authWorkspaceId?: UUID | undefined;
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* — an explicit, human-invoked orchestrator: authorize
|
|
156
|
+
* the matching `settings.reset.*` permission once, then loop `clear` for
|
|
157
|
+
* every setting in the namespace in the reset-authorized internal context
|
|
158
|
+
* (`skipAuthorize: true`) — the outer reset permission is sufficient on its
|
|
159
|
+
* own; each inner clear still emits its own `op='clear'` revision.
|
|
160
|
+
*
|
|
161
|
+
* `revisionSeqs` collects each inner `clear` call's own `revisionSeq` so a
|
|
162
|
+
* host's admin HTTP route can surface the full contract without a second
|
|
163
|
+
* read. Existing callers that only read `.clearedCount` are unaffected.
|
|
164
|
+
* See docs/decisions/DR-003-settings-ledger-invariants.md.
|
|
165
|
+
*/
|
|
166
|
+
export declare function resetNamespace(required: ResetNamespaceRequired, keysInNamespace: string[]): Promise<{
|
|
167
|
+
clearedCount: number;
|
|
168
|
+
revisionSeqs: number[];
|
|
169
|
+
}>;
|
|
170
|
+
export interface RenameDefinitionRequired {
|
|
171
|
+
deps: SettingsWriteServiceDeps;
|
|
172
|
+
input: {
|
|
173
|
+
namespace: string;
|
|
174
|
+
key: string;
|
|
175
|
+
workspaceId: UUID | null;
|
|
176
|
+
newNamespace: string;
|
|
177
|
+
newKey: string;
|
|
178
|
+
callerPrincipalId: UUID;
|
|
179
|
+
/** The workspace the caller is authorizing in (see `registerDefinitions`' identical field). */
|
|
180
|
+
authWorkspaceId: UUID;
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* The rename mechanism : a same-tx pair —
|
|
185
|
+
* (1) UPDATE the active definition row's `(namespace,key)` to the new name,
|
|
186
|
+
* same `setting_id`/`version` (ledgered `op='alias'`); (2) INSERT a fresh v1
|
|
187
|
+
* alias marker at the OLD name pointing at the new name. Because identity
|
|
188
|
+
* never moves, value rows (keyed on `setting_id` only) stay attached.
|
|
189
|
+
*
|
|
190
|
+
* Sequential rename (A->B then B->C) retargets every prior marker pointing
|
|
191
|
+
* at the OLD name to the NEW name in the same tx. A rename target that
|
|
192
|
+
* itself resolves to an existing alias is rejected `ALIAS_DEPTH_EXCEEDED`
|
|
193
|
+
* (behavior.spec.md §7: "the rename target resolves to an alias").
|
|
194
|
+
*
|
|
195
|
+
* Never touches `schema`/`defaultValue`/`scopes` -- a pure rename can never
|
|
196
|
+
* trigger `RENAME_RETYPE_CONFLICT` by construction; that guard lives in
|
|
197
|
+
* `retypeDefinition` ("no rename+retype in one op").
|
|
198
|
+
* See docs/decisions/DR-003-settings-ledger-invariants.md.
|
|
199
|
+
*/
|
|
200
|
+
export declare function renameDefinition(required: RenameDefinitionRequired): Promise<{
|
|
201
|
+
settingId: string;
|
|
202
|
+
markerSettingId: string;
|
|
203
|
+
}>;
|
|
204
|
+
export interface RetypeDefinitionRequired {
|
|
205
|
+
deps: SettingsWriteServiceDeps;
|
|
206
|
+
input: {
|
|
207
|
+
namespace: string;
|
|
208
|
+
key: string;
|
|
209
|
+
workspaceId: UUID | null;
|
|
210
|
+
schema: SettingValueSchema;
|
|
211
|
+
defaultValue: JsonValue | null;
|
|
212
|
+
/** A total coercer id/tag ( registry in `settings.ts`) for reading values recorded under any prior version. See docs/decisions/DR-003-settings-ledger-invariants.md. */
|
|
213
|
+
coercionTag: string;
|
|
214
|
+
/**
|
|
215
|
+
* Present only to detect a combined rename+retype request;
|
|
216
|
+
* retype never actually moves `(namespace,key)` -- if provided and it
|
|
217
|
+
* differs from the current name while `schema` also differs, the whole
|
|
218
|
+
* op is rejected `RENAME_RETYPE_CONFLICT` rather than silently doing
|
|
219
|
+
* only the schema half.
|
|
220
|
+
*/
|
|
221
|
+
newNamespace?: string | undefined;
|
|
222
|
+
newKey?: string | undefined;
|
|
223
|
+
callerPrincipalId: UUID;
|
|
224
|
+
authWorkspaceId: UUID;
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* The retype mechanism : a same-tx pair --
|
|
229
|
+
* (1) UPDATE the prior active version's `status` to `deprecated` FIRST (else
|
|
230
|
+
* the insert in step 2 collides with the one-active-row-per-slot
|
|
231
|
+
* invariant); (2) INSERT the new `version+1` row as `active`, same
|
|
232
|
+
* `setting_id`/`namespace`/`key`. Rejected unless every prior version
|
|
233
|
+
* (2..N) already carries a total coercer -- `coercionTag` is `null` only for
|
|
234
|
+
* version 1 by construction (`types.ts`), so this walks 2..N and requires
|
|
235
|
+
* each to be non-null.
|
|
236
|
+
* See docs/decisions/DR-003-settings-ledger-invariants.md.
|
|
237
|
+
*/
|
|
238
|
+
export declare function retypeDefinition(required: RetypeDefinitionRequired): Promise<{
|
|
239
|
+
settingId: string;
|
|
240
|
+
version: number;
|
|
241
|
+
}>;
|
|
242
|
+
export interface ReconcileDefinitionDefaultRequired {
|
|
243
|
+
deps: SettingsWriteServiceDeps;
|
|
244
|
+
input: {
|
|
245
|
+
namespace: string;
|
|
246
|
+
key: string;
|
|
247
|
+
workspaceId: UUID | null;
|
|
248
|
+
/** The default the SOURCE declares. Wins over a differing stored default. */
|
|
249
|
+
defaultValue: JsonValue;
|
|
250
|
+
callerPrincipalId: UUID;
|
|
251
|
+
authWorkspaceId: UUID;
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Reconciles a stored `default_json` that has drifted from the default its
|
|
256
|
+
* source declares. Idempotent and a no-op when they already agree.
|
|
257
|
+
*
|
|
258
|
+
* Why this exists — the bug it closes:
|
|
259
|
+
* `ensure-definitions.ts` registers each definition once and then skips it
|
|
260
|
+
* forever (`if (existing) continue;`). That makes a changed `defaultValue` in
|
|
261
|
+
* SOURCE unreachable in any install that has already booted, for every
|
|
262
|
+
* settings-dialog tab a host registers this way. It can surface as a stored
|
|
263
|
+
* default staying "system" in the database while source says "light",
|
|
264
|
+
* rendering a settings panel with the wrong initial state — a visibly wrong
|
|
265
|
+
* value produced by entirely correct-looking source. The next occurrence
|
|
266
|
+
* could be a silently wrong default with no visual tell at all.
|
|
267
|
+
*
|
|
268
|
+
* Why `core`-only:
|
|
269
|
+
* `ownerKind` already encodes who owns a definition. `core` definitions
|
|
270
|
+
* configure a platform capability and are code-owned, so code is the authority
|
|
271
|
+
* on their default and may overwrite a drifted stored one. `site` and `theme`
|
|
272
|
+
* definitions are operator-owned — silently overwriting those would destroy a
|
|
273
|
+
* deliberate choice, so they are rejected rather than reconciled.
|
|
274
|
+
*
|
|
275
|
+
* Why this is NOT a `retype`:
|
|
276
|
+
* `retype` deprecates the active row and inserts `version+1` because a changed
|
|
277
|
+
* SCHEMA means every stored value needs a total coercer. A changed DEFAULT
|
|
278
|
+
* needs none — the schema is untouched, so every stored value stays valid and
|
|
279
|
+
* only the resolution of UNSET values moves. The row is therefore updated in
|
|
280
|
+
* place at the same version, and the paired revision carries the old and new
|
|
281
|
+
* default in `beforeJson`/`afterJson` so the change is auditable.
|
|
282
|
+
*
|
|
283
|
+
* @complexity O(1) — one definition lookup plus at most one row update and one
|
|
284
|
+
* revision append, in a single transaction.
|
|
285
|
+
*/
|
|
286
|
+
export declare function reconcileDefinitionDefault(required: ReconcileDefinitionDefaultRequired): Promise<{
|
|
287
|
+
settingId: string;
|
|
288
|
+
changed: boolean;
|
|
289
|
+
}>;
|
|
290
|
+
export interface DeprecateDefinitionRequired {
|
|
291
|
+
deps: SettingsWriteServiceDeps;
|
|
292
|
+
input: {
|
|
293
|
+
namespace: string;
|
|
294
|
+
key: string;
|
|
295
|
+
workspaceId: UUID | null;
|
|
296
|
+
callerPrincipalId: UUID;
|
|
297
|
+
authWorkspaceId: UUID;
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
export interface TombstoneDefinitionRequired {
|
|
301
|
+
deps: SettingsWriteServiceDeps;
|
|
302
|
+
input: {
|
|
303
|
+
namespace: string;
|
|
304
|
+
key: string;
|
|
305
|
+
workspaceId: UUID | null;
|
|
306
|
+
callerPrincipalId: UUID;
|
|
307
|
+
authWorkspaceId: UUID;
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
/** Flips the active definition's status to `deprecated`, ledgered `op='deprecate'` -- same-tx, chokepoint-gated. */
|
|
311
|
+
export declare function deprecateDefinition(required: DeprecateDefinitionRequired): Promise<{
|
|
312
|
+
settingId: string;
|
|
313
|
+
version: number;
|
|
314
|
+
}>;
|
|
315
|
+
/** Flips the active definition's status to `tombstone` (kills a core key), ledgered `op='tombstone'` -- same-tx, chokepoint-gated. */
|
|
316
|
+
export declare function tombstoneDefinition(required: TombstoneDefinitionRequired): Promise<{
|
|
317
|
+
settingId: string;
|
|
318
|
+
version: number;
|
|
319
|
+
}>;
|
|
320
|
+
//# sourceMappingURL=write-service.d.ts.map
|