@odla-ai/brand 0.2.0 → 0.3.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/README.md +113 -5
- package/dist/{index-bj73h3qo.d.cts → index-CRl3IXHB.d.cts} +12 -168
- package/dist/{index-bj73h3qo.d.ts → index-CRl3IXHB.d.ts} +12 -168
- package/dist/index.cjs +2104 -331
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +655 -75
- package/dist/index.d.ts +655 -75
- package/dist/index.js +2105 -332
- package/dist/index.js.map +1 -1
- package/dist/tokens/index.d.cts +1 -1
- package/dist/tokens/index.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,340 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { P as ProposalKind, a as ProposalStatus, A as AssetKind, b as AssetAnalysis, B as BookStatus, c as BrandTokensSnapshot, d as PaletteStatus, S as Swatch, e as PaletteSource, f as SectionKind, g as SectionStatus } from './index-CRl3IXHB.js';
|
|
2
|
+
export { h as ASSET_KINDS, i as BOOK_STATUSES, j as BRAND_CHART_TOKENS, k as BRAND_CHAT_TOKENS, l as BRAND_DERIVED_TOKENS, m as BRAND_EMITTED_TOKENS, n as BRAND_NS, o as BRAND_REQUIRED_TOKENS, p as BrandTokens, C as CompileInput, q as CompiledBrandTokens, D as DARK_FLIP_L_MAX, r as DARK_FLIP_L_MIN, s as DEFAULT_ACCENT_SEED, I as ImagerySection, L as LogoSection, M as MapResult, t as PALETTE_SOURCES, u as PALETTE_STATUSES, v as PROPOSAL_KINDS, w as PROPOSAL_STATUSES, x as PaletteSection, R as RenderTokensCssOptions, y as SECTION_KINDS, z as SECTION_STATUSES, E as SWATCH_ROLES, F as SwatchRole, T as TokenWarning, G as TypographySection, V as VoiceSection, H as compileBrandTokens, J as deriveDarkTokens, K as mapPaletteToTokens, N as renderTokensCss } from './index-CRl3IXHB.js';
|
|
3
3
|
import { ToolHandler, Skill, ToolDef, Persona, Inference, AgentRunInput, ImageBlock, OracleContentBlock } from '@odla-ai/ai';
|
|
4
4
|
|
|
5
|
+
/** Immutable storage snapshot captured by the trusted semantic Brand bridge. */
|
|
6
|
+
interface BrandSourceAssetSnapshot {
|
|
7
|
+
assetId: string;
|
|
8
|
+
contentDigest: string;
|
|
9
|
+
objectEtag: string;
|
|
10
|
+
objectSize: number;
|
|
11
|
+
pathDigest: string;
|
|
12
|
+
contentType: string | null;
|
|
13
|
+
analysisRevision: number | null;
|
|
14
|
+
analysisDigest: string | null;
|
|
15
|
+
}
|
|
16
|
+
/** Required proposal provenance. Nulls keep the reviewed snapshot lossless. */
|
|
17
|
+
interface BrandProposalProvenance {
|
|
18
|
+
sourceAssetId: string | null;
|
|
19
|
+
sourceAsset: BrandSourceAssetSnapshot | null;
|
|
20
|
+
messageId: string | null;
|
|
21
|
+
turnId: string | null;
|
|
22
|
+
taintLabels: string[];
|
|
23
|
+
}
|
|
24
|
+
/** Agent output parked for explicit human resolution. */
|
|
25
|
+
interface BrandProposal {
|
|
26
|
+
id: string;
|
|
27
|
+
bookId: string;
|
|
28
|
+
kind: ProposalKind;
|
|
29
|
+
status: ProposalStatus;
|
|
30
|
+
payload: Record<string, unknown>;
|
|
31
|
+
rationale: string;
|
|
32
|
+
provenance: BrandProposalProvenance;
|
|
33
|
+
reviewDigest: string;
|
|
34
|
+
audience: string[];
|
|
35
|
+
createdBy: string;
|
|
36
|
+
createdAuthorityRef: string;
|
|
37
|
+
createdAt: number;
|
|
38
|
+
resolvedBy?: string;
|
|
39
|
+
resolvedAt?: number;
|
|
40
|
+
resolutionNote?: string;
|
|
41
|
+
approvedBy?: string;
|
|
42
|
+
appliedBy?: string;
|
|
43
|
+
resolutionReceiptId?: string;
|
|
44
|
+
resolutionActionDigest?: string;
|
|
45
|
+
}
|
|
46
|
+
/** Immutable proposal fields a human sends back when resolving it. */
|
|
47
|
+
interface BrandProposalReviewSnapshot {
|
|
48
|
+
id: string;
|
|
49
|
+
bookId: string;
|
|
50
|
+
kind: ProposalKind;
|
|
51
|
+
status: "open";
|
|
52
|
+
payload: Record<string, unknown>;
|
|
53
|
+
rationale: string;
|
|
54
|
+
provenance: BrandProposalProvenance;
|
|
55
|
+
reviewDigest: string;
|
|
56
|
+
audience: string[];
|
|
57
|
+
createdBy: string;
|
|
58
|
+
createdAuthorityRef: string;
|
|
59
|
+
createdAt: number;
|
|
60
|
+
}
|
|
61
|
+
/** Host receipt returned after consuming one central human-exact decision. */
|
|
62
|
+
interface BrandHumanAuthorityConsumption {
|
|
63
|
+
id: string;
|
|
64
|
+
grantId: string;
|
|
65
|
+
grantVersion: number;
|
|
66
|
+
useNumber: number;
|
|
67
|
+
actorPrincipalId: string;
|
|
68
|
+
actorKind: "human";
|
|
69
|
+
credentialId: string;
|
|
70
|
+
credentialKind: "clerk";
|
|
71
|
+
appId: string;
|
|
72
|
+
/** Exact Registry project lifetime authorized for this Brand decision. */
|
|
73
|
+
appIncarnation: string;
|
|
74
|
+
capability: "brand.proposal.resolve";
|
|
75
|
+
projectCapability: "brand.approve";
|
|
76
|
+
effect: "internal";
|
|
77
|
+
actionDigest: string;
|
|
78
|
+
resourceDigest: string;
|
|
79
|
+
constraintEvidence: Record<string, unknown>;
|
|
80
|
+
consumptionIdempotencyKey: string;
|
|
81
|
+
requestDigest: string;
|
|
82
|
+
consumedAt: number;
|
|
83
|
+
}
|
|
84
|
+
/** Live dependency revision and intended effect consumed by the decision. */
|
|
85
|
+
interface BrandDecisionBinding {
|
|
86
|
+
version: 1;
|
|
87
|
+
bookVersion: number;
|
|
88
|
+
activationRevision: number;
|
|
89
|
+
activePaletteId: string | null;
|
|
90
|
+
memberIdsDigest: string;
|
|
91
|
+
activePaletteDigest: string | null;
|
|
92
|
+
typographyDigest: string | null;
|
|
93
|
+
sourceAssetDigest: string | null;
|
|
94
|
+
effectDigest: string;
|
|
95
|
+
}
|
|
96
|
+
/** Durable projection of one centrally authorized decision. */
|
|
97
|
+
interface BrandApprovalReceipt {
|
|
98
|
+
version: 1;
|
|
99
|
+
id: string;
|
|
100
|
+
mutationKey: string;
|
|
101
|
+
bookId: string;
|
|
102
|
+
proposalId: string;
|
|
103
|
+
resolution: "accepted" | "rejected";
|
|
104
|
+
paletteId?: string;
|
|
105
|
+
resolutionNote?: string;
|
|
106
|
+
reviewedProposal: BrandProposalReviewSnapshot;
|
|
107
|
+
actionDigest: string;
|
|
108
|
+
decisionBinding: BrandDecisionBinding;
|
|
109
|
+
approvedBy: string;
|
|
110
|
+
approvedByKind: "human";
|
|
111
|
+
appliedBy: string;
|
|
112
|
+
appliedByKind: "human";
|
|
113
|
+
authorityRef: string;
|
|
114
|
+
authorityCapability: "brand.approve";
|
|
115
|
+
authorityConsumption: BrandHumanAuthorityConsumption;
|
|
116
|
+
createdAt: number;
|
|
117
|
+
receiptDigest: string;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Scalar values odla-db attrs and where-clauses accept. */
|
|
121
|
+
type BrandScalar = string | number | boolean | null;
|
|
122
|
+
/** Natural-key lookup ref for idempotent upserts (odla-db `Lookup` shape). */
|
|
123
|
+
interface BrandLookup {
|
|
124
|
+
ns: string;
|
|
125
|
+
attr: string;
|
|
126
|
+
value: BrandScalar;
|
|
127
|
+
}
|
|
128
|
+
/** How an op names its row: a raw entity id, or a natural-key lookup. */
|
|
129
|
+
type BrandEntityRef = string | BrandLookup;
|
|
130
|
+
/** Attr payload of one op. Typed `any` on purpose: the real odla-db
|
|
131
|
+
* `transact` constrains attrs to its own `Value` type, and `any` is the one
|
|
132
|
+
* shape assignable in both directions with no cast. */
|
|
133
|
+
type BrandAttrs = Record<string, any>;
|
|
134
|
+
/** One transact operation (update = attr-merge upsert; merge = deep-merge
|
|
135
|
+
* into a json attribute; retract = clear the named attributes, since a typed
|
|
136
|
+
* scalar can't store null). */
|
|
137
|
+
type BrandOp = {
|
|
138
|
+
t: "update";
|
|
139
|
+
ns: string;
|
|
140
|
+
id: BrandEntityRef;
|
|
141
|
+
attrs: BrandAttrs;
|
|
142
|
+
} | {
|
|
143
|
+
t: "merge";
|
|
144
|
+
ns: string;
|
|
145
|
+
id: BrandEntityRef;
|
|
146
|
+
attrs: BrandAttrs;
|
|
147
|
+
} | {
|
|
148
|
+
t: "retract";
|
|
149
|
+
ns: string;
|
|
150
|
+
id: BrandEntityRef;
|
|
151
|
+
attrs: string[];
|
|
152
|
+
} | {
|
|
153
|
+
t: "delete";
|
|
154
|
+
ns: string;
|
|
155
|
+
id: BrandEntityRef;
|
|
156
|
+
} | {
|
|
157
|
+
t: "link";
|
|
158
|
+
ns: string;
|
|
159
|
+
id: BrandEntityRef;
|
|
160
|
+
label: string;
|
|
161
|
+
target: BrandEntityRef;
|
|
162
|
+
} | {
|
|
163
|
+
t: "unlink";
|
|
164
|
+
ns: string;
|
|
165
|
+
id: BrandEntityRef;
|
|
166
|
+
label: string;
|
|
167
|
+
target: BrandEntityRef;
|
|
168
|
+
};
|
|
169
|
+
/** A row as odla-db returns it: hydrated id plus attrs. */
|
|
170
|
+
type BrandRow = {
|
|
171
|
+
id: string;
|
|
172
|
+
} & Record<string, unknown>;
|
|
173
|
+
/** Query result: namespace → rows. */
|
|
174
|
+
type BrandResult = Record<string, BrandRow[]>;
|
|
175
|
+
/** A brand book row: the auth roster (`memberIds`, including the bot agent
|
|
176
|
+
* id) plus the active palette and compiled-token cache. */
|
|
177
|
+
interface BrandBook {
|
|
178
|
+
id: string;
|
|
179
|
+
/** Monotonic worker-managed metadata revision. */
|
|
180
|
+
version: number;
|
|
181
|
+
slug: string;
|
|
182
|
+
name: string;
|
|
183
|
+
status: BookStatus;
|
|
184
|
+
ownerId: string;
|
|
185
|
+
/** Host authority that allowed this worker-created book. */
|
|
186
|
+
createdAuthorityRef: string;
|
|
187
|
+
rosterAuthorityRef?: string;
|
|
188
|
+
memberIds: string[];
|
|
189
|
+
channelId?: string;
|
|
190
|
+
activePaletteId?: string;
|
|
191
|
+
/** CAS counter advanced by every accepted palette activation. */
|
|
192
|
+
activationRevision: number;
|
|
193
|
+
tokens?: BrandTokensSnapshot;
|
|
194
|
+
summary?: string;
|
|
195
|
+
createdAt: number;
|
|
196
|
+
updatedAt: number;
|
|
197
|
+
}
|
|
198
|
+
/** A section row — one per (book, kind), upserted by its natural `key`. */
|
|
199
|
+
interface BrandSection {
|
|
200
|
+
id: string;
|
|
201
|
+
key: string;
|
|
202
|
+
bookId: string;
|
|
203
|
+
kind: SectionKind;
|
|
204
|
+
status: SectionStatus;
|
|
205
|
+
content: Record<string, unknown>;
|
|
206
|
+
audience: string[];
|
|
207
|
+
updatedBy: string;
|
|
208
|
+
updatedAt: number;
|
|
209
|
+
/** Present on approved sections and bound to the exact human decision. */
|
|
210
|
+
approvalReceiptId?: string;
|
|
211
|
+
approvalActionDigest?: string;
|
|
212
|
+
}
|
|
213
|
+
/** A palette row. Swatches are json ON the palette, not a namespace: the
|
|
214
|
+
* palette is the atomic proposal/approval unit and swatches are never
|
|
215
|
+
* queried across palettes. */
|
|
216
|
+
interface BrandPalette {
|
|
217
|
+
id: string;
|
|
218
|
+
bookId: string;
|
|
219
|
+
name: string;
|
|
220
|
+
status: PaletteStatus;
|
|
221
|
+
swatches: Swatch[];
|
|
222
|
+
seedHex?: string;
|
|
223
|
+
source: PaletteSource;
|
|
224
|
+
rationale?: string;
|
|
225
|
+
/** Accepted proposal whose exact reviewed payload materialized this row. */
|
|
226
|
+
proposalId: string;
|
|
227
|
+
approvalReceiptId: string;
|
|
228
|
+
approvalActionDigest: string;
|
|
229
|
+
audience: string[];
|
|
230
|
+
createdAt: number;
|
|
231
|
+
updatedAt: number;
|
|
232
|
+
}
|
|
233
|
+
/** An asset row mirroring one real uploaded file (worker-mediated; rules
|
|
234
|
+
* close the namespace). Delete is a tombstone (`deletedAt`), never a row
|
|
235
|
+
* delete, so analyses/proposals referencing it stay coherent. */
|
|
236
|
+
interface BrandAsset {
|
|
237
|
+
id: string;
|
|
238
|
+
bookId: string;
|
|
239
|
+
kind: AssetKind;
|
|
240
|
+
path: string;
|
|
241
|
+
storageObjectId: string;
|
|
242
|
+
contentDigest: string;
|
|
243
|
+
contentType: string;
|
|
244
|
+
size: number;
|
|
245
|
+
status: "live" | "deleting" | "deleted";
|
|
246
|
+
title?: string;
|
|
247
|
+
analysis?: AssetAnalysis;
|
|
248
|
+
analyzedAt?: number;
|
|
249
|
+
analysisRevision: number;
|
|
250
|
+
analysisDigest?: string;
|
|
251
|
+
analyzedBy?: string;
|
|
252
|
+
analyzedAuthorityRef?: string;
|
|
253
|
+
audience: string[];
|
|
254
|
+
uploadedBy: string;
|
|
255
|
+
uploadedAuthorityRef: string;
|
|
256
|
+
createdAt: number;
|
|
257
|
+
deletedAt?: number;
|
|
258
|
+
deletedBy?: string;
|
|
259
|
+
deletedAuthorityRef?: string;
|
|
260
|
+
}
|
|
261
|
+
/** What `db.storage.upload` resolves to (odla-db's file record shape). */
|
|
262
|
+
interface BrandFileRecord {
|
|
263
|
+
id: string;
|
|
264
|
+
path: string;
|
|
265
|
+
url: string;
|
|
266
|
+
size: number;
|
|
267
|
+
contentType: string;
|
|
268
|
+
}
|
|
269
|
+
/** Bodies `storage.upload` accepts — a practical subset of the platform's
|
|
270
|
+
* `BodyInit` (which has no ambient type under a DOM-less lib). The real
|
|
271
|
+
* @odla-ai/db client accepts a superset, so it still structurally satisfies
|
|
272
|
+
* {@link BrandStorage}. */
|
|
273
|
+
type BrandUploadBody = string | Blob | ArrayBuffer | Uint8Array | ReadableStream<Uint8Array>;
|
|
274
|
+
/** The injected file store — @odla-ai/db's `storage` API satisfies this. */
|
|
275
|
+
interface BrandStorage {
|
|
276
|
+
upload(path: string, data: BrandUploadBody, contentType?: string, opts?: {
|
|
277
|
+
private?: boolean;
|
|
278
|
+
}): Promise<BrandFileRecord>;
|
|
279
|
+
sign(path: string, ttlSeconds?: number): Promise<string>;
|
|
280
|
+
delete(path: string): Promise<void>;
|
|
281
|
+
}
|
|
282
|
+
/** One entity-state compare-and-swap condition, checked atomically with the
|
|
283
|
+
* transaction. Mirrors @odla-ai/db's structural guard contract. */
|
|
284
|
+
interface BrandTransactGuard {
|
|
285
|
+
ns: string;
|
|
286
|
+
id: string;
|
|
287
|
+
exists: boolean;
|
|
288
|
+
equals?: Record<string, unknown>;
|
|
289
|
+
}
|
|
290
|
+
/** Attribution, idempotency, and atomic preconditions for a brand write. */
|
|
291
|
+
interface BrandTransactOptions {
|
|
292
|
+
mutationId?: string;
|
|
293
|
+
guards?: BrandTransactGuard[];
|
|
294
|
+
asUser?: string;
|
|
295
|
+
asEmail?: string;
|
|
296
|
+
asPrincipalKind?: "human" | "agent" | "service";
|
|
297
|
+
}
|
|
298
|
+
/** The injected odla client (structural — a real @odla-ai/db `AdminDb`
|
|
299
|
+
* satisfies it). `transact` accepts flat op arrays; stable mutation ids give
|
|
300
|
+
* exactly-once application and guards bind reviewed state to its write. */
|
|
301
|
+
interface BrandDb {
|
|
302
|
+
query(q: Record<string, unknown>): Promise<Record<string, unknown[]>>;
|
|
303
|
+
transact(ops: unknown[], opts?: BrandTransactOptions): Promise<{
|
|
304
|
+
txId: number;
|
|
305
|
+
duplicate?: boolean;
|
|
306
|
+
}>;
|
|
307
|
+
storage: BrandStorage;
|
|
308
|
+
}
|
|
309
|
+
/** Who is acting: a human member or the book's bot agent. */
|
|
310
|
+
interface BrandActor {
|
|
311
|
+
id: string;
|
|
312
|
+
kind: "human" | "agent";
|
|
313
|
+
email?: string;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/** Canonical least-privilege runtime profile for a Brand collaborator agent. */
|
|
317
|
+
interface BrandAgentProfile {
|
|
318
|
+
version: 1;
|
|
319
|
+
projectCapabilities: readonly ["brand.read", "brand.edit"];
|
|
320
|
+
semanticOperations: readonly [
|
|
321
|
+
"brand.proposal.create",
|
|
322
|
+
"brand.asset.analysis.record",
|
|
323
|
+
"brand.asset.content.read"
|
|
324
|
+
];
|
|
325
|
+
rawBrandWrites: false;
|
|
326
|
+
rawFileOperations: false;
|
|
327
|
+
approval: {
|
|
328
|
+
principalKind: "human";
|
|
329
|
+
projectCapability: "brand.approve";
|
|
330
|
+
capability: "brand.proposal.resolve";
|
|
331
|
+
exactAction: true;
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
/** Install-time contract: agents use semantic Brand operations; only a direct
|
|
335
|
+
* human may consume exact approval authority for a reviewed proposal. */
|
|
336
|
+
declare const BRAND_AGENT_PROFILE: BrandAgentProfile;
|
|
337
|
+
|
|
5
338
|
/** Caller-fault error (bad hex, oversized payload, blocked transition…) — the
|
|
6
339
|
* route layer maps it to a 400. `fields` carries per-field messages when the
|
|
7
340
|
* failure came from input validation. */
|
|
@@ -13,6 +346,27 @@ declare class BrandInputError extends Error {
|
|
|
13
346
|
declare class BrandNotFoundError extends Error {
|
|
14
347
|
constructor(what: string);
|
|
15
348
|
}
|
|
349
|
+
/** A once-valid central authority/resource is permanently unavailable. */
|
|
350
|
+
declare class BrandGoneError extends Error {
|
|
351
|
+
constructor(message?: string);
|
|
352
|
+
}
|
|
353
|
+
/** Authenticated principal lacks the required principal kind/capability. */
|
|
354
|
+
declare class BrandForbiddenError extends Error {
|
|
355
|
+
constructor(message?: string);
|
|
356
|
+
}
|
|
357
|
+
/** Reviewed state or an idempotent action no longer matches current state. */
|
|
358
|
+
declare class BrandConflictError extends Error {
|
|
359
|
+
constructor(message: string);
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* A proposal authority use was consumed, but the local guarded Brand write
|
|
363
|
+
* lost its compare-and-swap race. Clients must preserve the reviewed draft but
|
|
364
|
+
* rotate their idempotency key before a fresh human decision attempt.
|
|
365
|
+
*/
|
|
366
|
+
declare class BrandReviewStateChangedError extends BrandConflictError {
|
|
367
|
+
readonly code = "brand_review_state_changed";
|
|
368
|
+
constructor(message?: string);
|
|
369
|
+
}
|
|
16
370
|
|
|
17
371
|
/** What `fetchBytes` resolves to: raw bytes plus the served content type. */
|
|
18
372
|
interface BrandFetchedBytes {
|
|
@@ -58,7 +412,7 @@ interface SerializedLinkEnd {
|
|
|
58
412
|
has: "one" | "many";
|
|
59
413
|
label: string;
|
|
60
414
|
}
|
|
61
|
-
/** A serialized schema link
|
|
415
|
+
/** A serialized schema link used for current-book authorization. */
|
|
62
416
|
interface SerializedLink {
|
|
63
417
|
forward: SerializedLinkEnd;
|
|
64
418
|
reverse: SerializedLinkEnd;
|
|
@@ -69,7 +423,7 @@ interface SerializedSchema {
|
|
|
69
423
|
links: Record<string, SerializedLink>;
|
|
70
424
|
}
|
|
71
425
|
/**
|
|
72
|
-
* The pre-serialized (wire-shape) odla-db schema for the
|
|
426
|
+
* The pre-serialized (wire-shape) odla-db schema for the six brand
|
|
73
427
|
* namespaces; POST it to `/app/:id/schema` as `{ schema: BRAND_SCHEMA }`.
|
|
74
428
|
* Natural keys (`book.slug`, `section.key`) make provisioning and section
|
|
75
429
|
* upserts idempotent; mirrored `id` attrs make rows addressable by
|
|
@@ -87,11 +441,11 @@ interface BrandRule {
|
|
|
87
441
|
/** Namespace → rule set, as installed at `/app/:id/admin/rules`. */
|
|
88
442
|
type BrandRules = Record<string, BrandRule>;
|
|
89
443
|
/**
|
|
90
|
-
* Default-deny CEL rules for the
|
|
444
|
+
* Default-deny CEL rules for the six brand namespaces; install at
|
|
91
445
|
* `/app/:id/admin/rules`. Books gate on the `memberIds` roster (owner-only
|
|
92
|
-
* writes);
|
|
93
|
-
*
|
|
94
|
-
*
|
|
446
|
+
* writes); child rows gate reads on current linked-book membership and all
|
|
447
|
+
* writes are worker-mediated. Use
|
|
448
|
+
* {@link brandRules} for a per-install copy.
|
|
95
449
|
*/
|
|
96
450
|
declare const BRAND_RULES: BrandRules;
|
|
97
451
|
/**
|
|
@@ -134,9 +488,8 @@ declare function assertSwatches(value: unknown): Swatch[];
|
|
|
134
488
|
*/
|
|
135
489
|
declare function assertSectionContent(kind: string, content: unknown): Record<string, unknown>;
|
|
136
490
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
* characters. Throws when nothing survives sanitizing.
|
|
491
|
+
* Validate an upload file name for an R2 key. Path/URL delimiters and control
|
|
492
|
+
* characters are rejected; leading dots are stripped and length is capped.
|
|
140
493
|
*/
|
|
141
494
|
declare function safeFileName(name: unknown): string;
|
|
142
495
|
/**
|
|
@@ -151,6 +504,64 @@ declare function assertAssetContentType(value: unknown): string;
|
|
|
151
504
|
*/
|
|
152
505
|
declare function assertAnalysis(value: unknown): AssetAnalysis;
|
|
153
506
|
|
|
507
|
+
/** Stay materially below the server's whole-guards parser budget. */
|
|
508
|
+
declare function isBoundedBrandJson(root: unknown, limits?: {
|
|
509
|
+
maxDepth?: number;
|
|
510
|
+
maxNodes?: number;
|
|
511
|
+
maxBytes?: number;
|
|
512
|
+
}): boolean;
|
|
513
|
+
/** Deterministic JSON with recursively sorted object keys. */
|
|
514
|
+
declare function canonicalBrandJson(value: unknown): string;
|
|
515
|
+
/** `sha256:<hex>` over {@link canonicalBrandJson}. */
|
|
516
|
+
declare function brandJsonDigest(value: unknown): Promise<string>;
|
|
517
|
+
|
|
518
|
+
/** Stable local reference to one immutable central grant revision. */
|
|
519
|
+
declare function brandAuthorityRef(consumption: Pick<BrandHumanAuthorityConsumption, "grantId" | "grantVersion">): string;
|
|
520
|
+
/** Validate the exact direct-human central authority receipt shape. */
|
|
521
|
+
declare function isBrandHumanAuthorityConsumption(value: unknown): value is BrandHumanAuthorityConsumption;
|
|
522
|
+
/** Verify exact shape, cross-field bindings, and every local digest. This
|
|
523
|
+
* proves receipt self-consistency only; the host must authenticate the
|
|
524
|
+
* central consumption behind `authorityConsumption.id`. */
|
|
525
|
+
declare function verifyBrandApprovalReceipt(receipt: unknown): Promise<boolean>;
|
|
526
|
+
|
|
527
|
+
/** Brand resources that can be shared into a Discussion message. */
|
|
528
|
+
declare const BRAND_DISCUSSION_REFERENCE_KINDS: readonly ["brand:book", "brand:asset", "brand:palette", "brand:proposal", "brand:receipt"];
|
|
529
|
+
/** One Brand resource kind understood by the native Brand destination. */
|
|
530
|
+
type BrandDiscussionReferenceKind = (typeof BRAND_DISCUSSION_REFERENCE_KINDS)[number];
|
|
531
|
+
/** Canonical Brand destination target parsed from an `odla-ref` deep link. */
|
|
532
|
+
interface BrandDiscussionReferenceTarget {
|
|
533
|
+
kind: BrandDiscussionReferenceKind;
|
|
534
|
+
bookId: string;
|
|
535
|
+
resourceId?: string;
|
|
536
|
+
}
|
|
537
|
+
/** Product-owned projection returned to Discussion typeahead and exact lookup. */
|
|
538
|
+
interface BrandDiscussionReference {
|
|
539
|
+
/** Canonical Brand kind used in stored Discussion ref markup. */
|
|
540
|
+
kind: BrandDiscussionReferenceKind;
|
|
541
|
+
/** Opaque durable product id; never infer membership from its segments. */
|
|
542
|
+
id: string;
|
|
543
|
+
/** Product-authored primary display name. */
|
|
544
|
+
label: string;
|
|
545
|
+
/** Short product-authored secondary context for the picker. */
|
|
546
|
+
hint: string;
|
|
547
|
+
/** Bounded product-authored context safe to show an LLM or person. */
|
|
548
|
+
summary: string;
|
|
549
|
+
/** Current product status at inspection time. */
|
|
550
|
+
status: string;
|
|
551
|
+
/** Human-readable native surface the link opens. */
|
|
552
|
+
destination: string;
|
|
553
|
+
/** Same-origin native link; navigation is not mutation authority. */
|
|
554
|
+
href: string;
|
|
555
|
+
}
|
|
556
|
+
/** Durable ref id: a book id, or `bookId/resourceId` for a child resource. */
|
|
557
|
+
declare function brandDiscussionReferenceId(target: BrandDiscussionReferenceTarget): string;
|
|
558
|
+
/** Canonical value stored in the stable `odla-ref` query parameter. */
|
|
559
|
+
declare function formatBrandDiscussionReference(target: BrandDiscussionReferenceTarget): string;
|
|
560
|
+
/** Parse and validate a Brand `odla-ref`; malformed and cross-product refs fail closed. */
|
|
561
|
+
declare function parseBrandDiscussionReference(input: URL | string): BrandDiscussionReferenceTarget | null;
|
|
562
|
+
/** Build the native Brand deep link while preserving the deployed origin. */
|
|
563
|
+
declare function brandDiscussionReferenceHref(current: URL, target: BrandDiscussionReferenceTarget, basePath?: string): string;
|
|
564
|
+
|
|
154
565
|
/** Input to {@link createBookOps}. `memberIds` is the full auth roster —
|
|
155
566
|
* include the bot agent's id so it can pass the audience rules. */
|
|
156
567
|
interface CreateBookInput {
|
|
@@ -158,6 +569,7 @@ interface CreateBookInput {
|
|
|
158
569
|
slug: string;
|
|
159
570
|
name: string;
|
|
160
571
|
ownerId: string;
|
|
572
|
+
createdAuthorityRef: string;
|
|
161
573
|
memberIds: string[];
|
|
162
574
|
channelId?: string;
|
|
163
575
|
now: number;
|
|
@@ -212,6 +624,8 @@ interface UpsertSectionInput {
|
|
|
212
624
|
audience: string[];
|
|
213
625
|
updatedBy: string;
|
|
214
626
|
now: number;
|
|
627
|
+
approvalReceiptId?: string;
|
|
628
|
+
approvalActionDigest?: string;
|
|
215
629
|
}
|
|
216
630
|
/**
|
|
217
631
|
* Ops to create-or-replace a book's section of one kind: a single `update`
|
|
@@ -220,6 +634,24 @@ interface UpsertSectionInput {
|
|
|
220
634
|
* snapshot, and the author/timestamp.
|
|
221
635
|
*/
|
|
222
636
|
declare function upsertSectionOps(input: UpsertSectionInput): BrandOp[];
|
|
637
|
+
/** Input for an agent-authored non-palette facet proposal. */
|
|
638
|
+
interface ProposeSectionInput {
|
|
639
|
+
id: string;
|
|
640
|
+
bookId: string;
|
|
641
|
+
kind: Exclude<SectionKind, "palette">;
|
|
642
|
+
content: Record<string, unknown>;
|
|
643
|
+
rationale: string;
|
|
644
|
+
audience: string[];
|
|
645
|
+
createdBy: string;
|
|
646
|
+
createdAuthorityRef: string;
|
|
647
|
+
sourceAsset?: BrandProposal["provenance"]["sourceAsset"];
|
|
648
|
+
messageId: string;
|
|
649
|
+
turnId: string;
|
|
650
|
+
taintLabels: string[];
|
|
651
|
+
now: number;
|
|
652
|
+
}
|
|
653
|
+
/** Validate a facet draft and park it as an immutable OPEN proposal. */
|
|
654
|
+
declare function proposeSectionOps(input: ProposeSectionInput): Promise<BrandOp[]>;
|
|
223
655
|
|
|
224
656
|
/** Input to {@link proposePaletteOps}. `audience` is the book's roster
|
|
225
657
|
* snapshot; `contrastReport` is stored verbatim in the payload for the
|
|
@@ -233,9 +665,12 @@ interface ProposePaletteInput {
|
|
|
233
665
|
seedHex?: string;
|
|
234
666
|
contrastReport?: unknown;
|
|
235
667
|
createdBy: string;
|
|
668
|
+
createdAuthorityRef: string;
|
|
236
669
|
audience: string[];
|
|
237
|
-
|
|
238
|
-
messageId
|
|
670
|
+
sourceAsset?: BrandProposal["provenance"]["sourceAsset"];
|
|
671
|
+
messageId: string;
|
|
672
|
+
turnId: string;
|
|
673
|
+
taintLabels: string[];
|
|
239
674
|
now: number;
|
|
240
675
|
}
|
|
241
676
|
/**
|
|
@@ -243,13 +678,15 @@ interface ProposePaletteInput {
|
|
|
243
678
|
* `kind: "palette"`, `status: "open"`, with the validated swatches (and
|
|
244
679
|
* optional seed/contrast report) in `payload`.
|
|
245
680
|
*/
|
|
246
|
-
declare function proposePaletteOps(input: ProposePaletteInput): BrandOp[]
|
|
681
|
+
declare function proposePaletteOps(input: ProposePaletteInput): Promise<BrandOp[]>;
|
|
247
682
|
/** Input to {@link acceptProposalOps}: the proposal row as read back, the id
|
|
248
683
|
* to mint the palette under, and who resolved it. */
|
|
249
684
|
interface AcceptProposalInput {
|
|
250
685
|
proposal: BrandProposal;
|
|
251
686
|
paletteId: string;
|
|
252
687
|
resolvedBy: string;
|
|
688
|
+
approvalReceiptId: string;
|
|
689
|
+
approvalActionDigest: string;
|
|
253
690
|
now: number;
|
|
254
691
|
resolutionNote?: string;
|
|
255
692
|
}
|
|
@@ -279,16 +716,18 @@ interface RejectProposalInput {
|
|
|
279
716
|
declare function rejectProposalOps(input: RejectProposalInput): BrandOp[];
|
|
280
717
|
|
|
281
718
|
/** Input to {@link createAssetOps} — the storage upload's receipt fields
|
|
282
|
-
* (`path`/`
|
|
719
|
+
* (`path`/`size`) plus the declared kind and the book's audience. */
|
|
283
720
|
interface CreateAssetInput {
|
|
284
721
|
id: string;
|
|
285
722
|
bookId: string;
|
|
286
723
|
kind: AssetKind;
|
|
287
724
|
path: string;
|
|
288
|
-
|
|
725
|
+
storageObjectId: string;
|
|
726
|
+
contentDigest: string;
|
|
289
727
|
contentType: string;
|
|
290
728
|
size: number;
|
|
291
729
|
uploadedBy: string;
|
|
730
|
+
uploadedAuthorityRef: string;
|
|
292
731
|
audience: string[];
|
|
293
732
|
title?: string;
|
|
294
733
|
now: number;
|
|
@@ -304,12 +743,14 @@ declare function createAssetOps(input: CreateAssetInput): BrandOp[];
|
|
|
304
743
|
* `deletedAt` in place. List reads exclude tombstoned rows; the row itself
|
|
305
744
|
* stays for provenance.
|
|
306
745
|
*/
|
|
307
|
-
declare function
|
|
746
|
+
declare function beginAssetDeleteOps(assetId: BrandEntityRef, now: number, deletedBy: string, deletedAuthorityRef: string): BrandOp[];
|
|
747
|
+
/** Complete a previously authorized deletion after storage is tombstoned. */
|
|
748
|
+
declare function finishAssetDeleteOps(assetId: BrandEntityRef): BrandOp[];
|
|
308
749
|
/**
|
|
309
750
|
* Ops to record an agent's analysis of an asset: the validated + capped
|
|
310
751
|
* analysis json plus `analyzedAt`. Replaces any prior analysis whole.
|
|
311
752
|
*/
|
|
312
|
-
declare function recordAnalysisOps(assetId: BrandEntityRef, analysis: unknown, now: number): BrandOp[]
|
|
753
|
+
declare function recordAnalysisOps(assetId: BrandEntityRef, analysis: unknown, priorRevision: number, analyzedBy: string, analyzedAuthorityRef: string, now: number): Promise<BrandOp[]>;
|
|
313
754
|
|
|
314
755
|
/** An sRGB color with channels as fractions in [0, 1]. */
|
|
315
756
|
interface Rgb {
|
|
@@ -566,6 +1007,21 @@ interface DerivePaletteOptions {
|
|
|
566
1007
|
*/
|
|
567
1008
|
declare function derivePalette(seedHex: string, opts?: DerivePaletteOptions): Swatch[];
|
|
568
1009
|
|
|
1010
|
+
/** Semantic Brand capability granted to one live agent principal. */
|
|
1011
|
+
type BrandCapability = "brand.read" | "brand.edit";
|
|
1012
|
+
/** Host-verified evidence that an agent currently holds one Brand capability. */
|
|
1013
|
+
interface BrandCapabilityAuthority {
|
|
1014
|
+
capability: BrandCapability;
|
|
1015
|
+
authorityRef: string;
|
|
1016
|
+
}
|
|
1017
|
+
/** Safe directory projection exposed to an agent for Brand attribution. */
|
|
1018
|
+
interface BrandPrincipalProjection {
|
|
1019
|
+
id: string;
|
|
1020
|
+
displayName: string;
|
|
1021
|
+
kind: "human" | "agent" | "service";
|
|
1022
|
+
managerDisplayName?: string;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
569
1025
|
/** The bot identity the skill writes as (`selfId` = the agent id carried in
|
|
570
1026
|
* the book's `memberIds` roster and every audience snapshot). */
|
|
571
1027
|
interface BrandSkillSelf {
|
|
@@ -573,6 +1029,32 @@ interface BrandSkillSelf {
|
|
|
573
1029
|
kind: "bot";
|
|
574
1030
|
displayName?: string;
|
|
575
1031
|
}
|
|
1032
|
+
/** Server-enforced semantic bridge. Raw agent credentials must be denied all
|
|
1033
|
+
* Brand namespace writes and raw file operations. */
|
|
1034
|
+
interface BrandAgentBridge {
|
|
1035
|
+
createProposal(input: {
|
|
1036
|
+
jobId: string;
|
|
1037
|
+
bookId: string;
|
|
1038
|
+
mutationId: string;
|
|
1039
|
+
kind: ProposalKind;
|
|
1040
|
+
payload: Record<string, unknown>;
|
|
1041
|
+
rationale: string;
|
|
1042
|
+
sourceAssetId?: string;
|
|
1043
|
+
}): Promise<BrandProposal>;
|
|
1044
|
+
recordAssetAnalysis(input: {
|
|
1045
|
+
jobId: string;
|
|
1046
|
+
mutationId: string;
|
|
1047
|
+
bookId: string;
|
|
1048
|
+
assetId: string;
|
|
1049
|
+
analysis: AssetAnalysis;
|
|
1050
|
+
expectedAnalysisRevision: number;
|
|
1051
|
+
}): Promise<BrandAsset>;
|
|
1052
|
+
readAssetContent(input: {
|
|
1053
|
+
jobId: string;
|
|
1054
|
+
bookId: string;
|
|
1055
|
+
assetId: string;
|
|
1056
|
+
}): Promise<BrandFetchedBytes>;
|
|
1057
|
+
}
|
|
576
1058
|
/** Options for {@link brandSkill}. */
|
|
577
1059
|
interface BrandSkillOpts {
|
|
578
1060
|
/** The injected odla client (a real @odla-ai/db AdminDb satisfies it). */
|
|
@@ -581,10 +1063,27 @@ interface BrandSkillOpts {
|
|
|
581
1063
|
bookId: string;
|
|
582
1064
|
/** The bot identity acting through these tools. */
|
|
583
1065
|
self: BrandSkillSelf;
|
|
584
|
-
/**
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
1066
|
+
/** Host attestation for the rules-scoped credential behind `db`. */
|
|
1067
|
+
agentDbBinding: {
|
|
1068
|
+
principalId: string;
|
|
1069
|
+
credentialRef: string;
|
|
1070
|
+
};
|
|
1071
|
+
/** Active verified agent job; the bridge derives message/turn provenance. */
|
|
1072
|
+
agentJobId: string;
|
|
1073
|
+
agentBridge: BrandAgentBridge;
|
|
1074
|
+
/** Host verification against the live principal grant. Missing/denied hooks
|
|
1075
|
+
* fail closed; roster membership is visibility, not authority. */
|
|
1076
|
+
authorizeCapability: (input: {
|
|
1077
|
+
agentId: string;
|
|
1078
|
+
bookId: string;
|
|
1079
|
+
capability: BrandCapability;
|
|
1080
|
+
}) => Promise<BrandCapabilityAuthority | null> | BrandCapabilityAuthority | null;
|
|
1081
|
+
/** Bounded host directory projection for conversational display only. */
|
|
1082
|
+
resolvePrincipals: (input: {
|
|
1083
|
+
requesterAgentId: string;
|
|
1084
|
+
bookId: string;
|
|
1085
|
+
principalIds: string[];
|
|
1086
|
+
}) => Promise<BrandPrincipalProjection[]>;
|
|
588
1087
|
/** False when the model cannot take image/document blocks inside a
|
|
589
1088
|
* tool_result — view_asset then steers to the pre-turn attachment path. */
|
|
590
1089
|
visionInToolResults?: boolean;
|
|
@@ -598,12 +1097,27 @@ interface BrandToolCtx {
|
|
|
598
1097
|
db: BrandDb;
|
|
599
1098
|
bookId: string;
|
|
600
1099
|
self: BrandSkillSelf;
|
|
601
|
-
fileBaseUrl: string;
|
|
602
|
-
fetchBytes: (url: string) => Promise<BrandFetchedBytes>;
|
|
603
1100
|
/** Whether image/document blocks may be returned inside tool results. */
|
|
604
1101
|
visionInToolResults: boolean;
|
|
605
1102
|
now: () => number;
|
|
606
1103
|
newId: () => string;
|
|
1104
|
+
agentJobId: string;
|
|
1105
|
+
createProposal(input: {
|
|
1106
|
+
mutationId: string;
|
|
1107
|
+
kind: ProposalKind;
|
|
1108
|
+
payload: Record<string, unknown>;
|
|
1109
|
+
rationale: string;
|
|
1110
|
+
sourceAssetId?: string;
|
|
1111
|
+
}): Promise<BrandProposal>;
|
|
1112
|
+
recordAssetAnalysis(input: {
|
|
1113
|
+
mutationId: string;
|
|
1114
|
+
assetId: string;
|
|
1115
|
+
analysis: AssetAnalysis;
|
|
1116
|
+
expectedAnalysisRevision: number;
|
|
1117
|
+
}): Promise<BrandAsset>;
|
|
1118
|
+
readAssetContent(assetId: string): Promise<BrandFetchedBytes>;
|
|
1119
|
+
resolvePrincipals(ids: string[]): Promise<BrandPrincipalProjection[]>;
|
|
1120
|
+
authority(capability: BrandCapability): Promise<BrandCapabilityAuthority>;
|
|
607
1121
|
/** Load the scoped book row; throws BrandNotFoundError when missing. */
|
|
608
1122
|
loadBook(): Promise<BrandBook>;
|
|
609
1123
|
/** Wrap a handler so Brand validation errors come back as actionable
|
|
@@ -638,17 +1152,13 @@ declare function base64FromBytes(bytes: Uint8Array): string;
|
|
|
638
1152
|
*/
|
|
639
1153
|
declare function assetTools(ctx: BrandToolCtx): ToolDef[];
|
|
640
1154
|
|
|
641
|
-
/**
|
|
642
|
-
* The book tools: `update_section` (validated per-kind content, upserted by
|
|
643
|
-
* natural key with the book's audience snapshot) and `compile_tokens`
|
|
644
|
-
* (palette + typography → light/dark token cache on the book row).
|
|
645
|
-
*/
|
|
1155
|
+
/** `update_section` validates a draft and parks it as an OPEN proposal. */
|
|
646
1156
|
declare function bookTools(ctx: BrandToolCtx): ToolDef[];
|
|
647
1157
|
|
|
648
1158
|
/**
|
|
649
1159
|
* The palette tools: `analyze_color`, `evaluate_contrast` (pure math),
|
|
650
1160
|
* `propose_palette` (writes an OPEN proposal with an automatic contrast
|
|
651
|
-
* report)
|
|
1161
|
+
* report). Resolution is deliberately not an agent tool.
|
|
652
1162
|
*/
|
|
653
1163
|
declare function paletteTools(ctx: BrandToolCtx): ToolDef[];
|
|
654
1164
|
|
|
@@ -699,15 +1209,71 @@ declare function supportsBrandVision(spec: BrandVisionSpec | null | undefined):
|
|
|
699
1209
|
*/
|
|
700
1210
|
declare function readTools(ctx: BrandToolCtx): ToolDef[];
|
|
701
1211
|
|
|
1212
|
+
type BrandRouteCapability = "brand.edit" | "app.manage";
|
|
1213
|
+
type BrandRouteEffect = "internal" | "destructive";
|
|
1214
|
+
interface BrandRouteAuthority {
|
|
1215
|
+
authorityRef: string;
|
|
1216
|
+
actorPrincipalId: string;
|
|
1217
|
+
capability: BrandRouteCapability;
|
|
1218
|
+
effect: BrandRouteEffect;
|
|
1219
|
+
}
|
|
702
1220
|
/** Everything {@link import("./index").createBrandRoutes} needs from the host worker. */
|
|
703
1221
|
interface BrandRouteOpts {
|
|
704
1222
|
/** The injected odla client (a real @odla-ai/db AdminDb satisfies it). */
|
|
705
1223
|
db: BrandDb;
|
|
1224
|
+
/** Registry app that owns the book rows and central authority records. */
|
|
1225
|
+
appId: string;
|
|
706
1226
|
/** Host-owned auth: resolve the request to an actor or null (→ 401). The
|
|
707
1227
|
* tokens routes skip this only when `publicTokens` is true. */
|
|
708
1228
|
authorize: (req: Request) => Promise<BrandActor | null> | BrandActor | null;
|
|
1229
|
+
/** Optional host-owned authority seam for read-only Discussion reference
|
|
1230
|
+
* lookup. Verify exact Brand product, brand.read capability, canonical
|
|
1231
|
+
* audience, principal, current app lifetime/environment, and agent grant
|
|
1232
|
+
* provenance here; when omitted, the ordinary request authorizer is used. */
|
|
1233
|
+
authorizeDiscussionReferences?: (req: Request) => Promise<BrandActor | null> | BrandActor | null;
|
|
1234
|
+
/** Live host verification for worker-mediated effects. The callback must
|
|
1235
|
+
* verify the direct human credential, current app owner/co-owner status,
|
|
1236
|
+
* exact capability/effect/resource, and return null on any uncertainty. */
|
|
1237
|
+
authorizeCapability: (input: {
|
|
1238
|
+
req: Request;
|
|
1239
|
+
actor: BrandActor;
|
|
1240
|
+
appId: string;
|
|
1241
|
+
bookId?: string;
|
|
1242
|
+
capability: BrandRouteCapability;
|
|
1243
|
+
effect: BrandRouteEffect;
|
|
1244
|
+
}) => Promise<BrandRouteAuthority | null> | BrandRouteAuthority | null;
|
|
1245
|
+
/** Consume or idempotently replay one registry `human_exact` authority use,
|
|
1246
|
+
* then reload and authenticate its immutable central receipt. Missing,
|
|
1247
|
+
* synthetic, cached, or unverifiable authority must return null. */
|
|
1248
|
+
consumeHumanExact: (input: {
|
|
1249
|
+
req: Request;
|
|
1250
|
+
actor: BrandActor;
|
|
1251
|
+
appId: string;
|
|
1252
|
+
capability: "brand.proposal.resolve";
|
|
1253
|
+
projectCapability: "brand.approve";
|
|
1254
|
+
effect: "internal";
|
|
1255
|
+
resource: {
|
|
1256
|
+
bookId: string;
|
|
1257
|
+
proposalId: string;
|
|
1258
|
+
};
|
|
1259
|
+
actionDigest: string;
|
|
1260
|
+
consumptionIdempotencyKey: string;
|
|
1261
|
+
}) => Promise<BrandHumanAuthorityConsumption | null> | BrandHumanAuthorityConsumption | null;
|
|
1262
|
+
/** Re-read the private object and authenticate the exact snapshot captured
|
|
1263
|
+
* by the agent bridge. This must verify path, ETag, size, and SHA-256 bytes;
|
|
1264
|
+
* returning false prevents authority consumption and the local effect. */
|
|
1265
|
+
verifySourceAssetSnapshot: (input: {
|
|
1266
|
+
req: Request;
|
|
1267
|
+
appId: string;
|
|
1268
|
+
bookId: string;
|
|
1269
|
+
assetId: string;
|
|
1270
|
+
path: string;
|
|
1271
|
+
snapshot: BrandSourceAssetSnapshot;
|
|
1272
|
+
}) => Promise<boolean> | boolean;
|
|
709
1273
|
/** Mount point. Default "/api/brand". */
|
|
710
1274
|
basePath?: string;
|
|
1275
|
+
/** Native UI mount used by returned Discussion deep links. Default "/". */
|
|
1276
|
+
discussionBasePath?: string;
|
|
711
1277
|
/** Upload size cap in bytes (checked against `File.size`). Default 8 MiB. */
|
|
712
1278
|
maxUploadBytes?: number;
|
|
713
1279
|
/** Serve `GET /books/:id/tokens.css` and `tokens.json` without authorize —
|
|
@@ -721,12 +1287,20 @@ interface BrandRouteOpts {
|
|
|
721
1287
|
/** Per-request context handed to the authorized route handlers. */
|
|
722
1288
|
interface BrandRouteCtx {
|
|
723
1289
|
db: BrandDb;
|
|
1290
|
+
appId: string;
|
|
724
1291
|
actor: BrandActor;
|
|
1292
|
+
authorizeCapability: BrandRouteOpts["authorizeCapability"];
|
|
1293
|
+
consumeHumanExact: BrandRouteOpts["consumeHumanExact"];
|
|
1294
|
+
verifySourceAssetSnapshot: BrandRouteOpts["verifySourceAssetSnapshot"];
|
|
725
1295
|
now: () => number;
|
|
726
1296
|
newId: () => string;
|
|
727
1297
|
maxUploadBytes: number;
|
|
1298
|
+
discussionBasePath: string;
|
|
728
1299
|
}
|
|
729
1300
|
|
|
1301
|
+
/** Freeze the exact OPEN proposal fields a reviewer sees. */
|
|
1302
|
+
declare function proposalReviewSnapshot(proposal: BrandProposal): BrandProposalReviewSnapshot;
|
|
1303
|
+
|
|
730
1304
|
/**
|
|
731
1305
|
* Build the brand fetch handler. Returns `null` for requests outside
|
|
732
1306
|
* `basePath` (default `/api/brand`) so the host worker falls through to its
|
|
@@ -737,11 +1311,13 @@ interface BrandRouteCtx {
|
|
|
737
1311
|
*/
|
|
738
1312
|
declare function createBrandRoutes(options: BrandRouteOpts): (req: Request) => Promise<Response | null>;
|
|
739
1313
|
|
|
740
|
-
/**
|
|
741
|
-
* the same wire shape chat-agent consumes (see the header provenance note). */
|
|
1314
|
+
/** Versioned, host-authenticated envelope for one Brand agent turn. */
|
|
742
1315
|
interface BrandDispatchBody {
|
|
743
|
-
v:
|
|
1316
|
+
v: 2;
|
|
744
1317
|
appId: string;
|
|
1318
|
+
/** Exact Registry app lifetime admitted by the durable Server job. */
|
|
1319
|
+
appIncarnation: string;
|
|
1320
|
+
jobId: string;
|
|
745
1321
|
trigger: {
|
|
746
1322
|
id: string;
|
|
747
1323
|
skill: string;
|
|
@@ -757,59 +1333,61 @@ interface BrandDispatchBody {
|
|
|
757
1333
|
row: Record<string, unknown>;
|
|
758
1334
|
};
|
|
759
1335
|
}
|
|
760
|
-
/**
|
|
761
|
-
* Validate an untrusted dispatch body; null if malformed. SHAPE-only,
|
|
762
|
-
* mirroring chat-agent's parseDispatch: it does NOT gate on `trigger.skill` —
|
|
763
|
-
* routing on skill is the HOST's job (a worker serving several skills checks
|
|
764
|
-
* `body.trigger.skill === "brand"` before calling {@link dispatchBrandTurn}),
|
|
765
|
-
* so an absent skill parses as `""`, never silently defaulted to "brand".
|
|
766
|
-
*/
|
|
767
|
-
declare function parseBrandDispatch(raw: unknown): BrandDispatchBody | null;
|
|
768
|
-
/** The brand book bound to a chat channel (`brand_book.channelId`), or null
|
|
769
|
-
* when the channel id is empty or no book claims it. */
|
|
770
|
-
declare function bookForChannel(db: BrandDb, channelId: string): Promise<BrandBook | null>;
|
|
771
|
-
/**
|
|
772
|
-
* The agent-turn input for a dispatched message: a brand-flavored prompt
|
|
773
|
-
* (mirrors chat-agent's `inputFor` tone, steering into the brand workflow),
|
|
774
|
-
* and — when pre-turn `attachments` are supplied (the no-vision-in-tool-
|
|
775
|
-
* results path) — an explicit block array with the images BEFORE the text.
|
|
776
|
-
*/
|
|
777
|
-
declare function brandInputFor(body: BrandDispatchBody, attachments?: ImageBlock[]): string | OracleContentBlock[];
|
|
778
|
-
/** Everything {@link dispatchBrandTurn} needs from the host worker. The
|
|
779
|
-
* @odla-ai/ai pieces (`inference`, `runAgent`) are injected so this module
|
|
780
|
-
* keeps the package's types-only relationship with the peer. */
|
|
1336
|
+
/** Trusted host seams required to run one capability-bound Brand agent turn. */
|
|
781
1337
|
interface BrandDispatchDeps {
|
|
782
|
-
/**
|
|
1338
|
+
/** Service read client; never handed to agent tools. */
|
|
783
1339
|
db: BrandDb;
|
|
784
|
-
|
|
1340
|
+
appId: string;
|
|
1341
|
+
/** Host-created runtime bound to this verified dispatch + exact agent. */
|
|
1342
|
+
agentRuntimeFor: (input: {
|
|
1343
|
+
appId: string;
|
|
1344
|
+
agentId: string;
|
|
1345
|
+
bookId: string;
|
|
1346
|
+
triggerId: string;
|
|
1347
|
+
eventId: string;
|
|
1348
|
+
jobId: string;
|
|
1349
|
+
}) => Promise<{
|
|
1350
|
+
db: BrandDb;
|
|
1351
|
+
credentialRef: string;
|
|
1352
|
+
jobId: string;
|
|
1353
|
+
bridge: BrandAgentBridge;
|
|
1354
|
+
}>;
|
|
1355
|
+
authorizeCapability: (input: {
|
|
1356
|
+
agentId: string;
|
|
1357
|
+
bookId: string;
|
|
1358
|
+
capability: "brand.read" | "brand.edit";
|
|
1359
|
+
}) => Promise<BrandCapabilityAuthority | null> | BrandCapabilityAuthority | null;
|
|
1360
|
+
resolvePrincipals: (input: {
|
|
1361
|
+
requesterAgentId: string;
|
|
1362
|
+
bookId: string;
|
|
1363
|
+
principalIds: string[];
|
|
1364
|
+
}) => Promise<BrandPrincipalProjection[]>;
|
|
785
1365
|
inference: Inference;
|
|
786
|
-
/** Canonical model id for the persona. */
|
|
787
1366
|
model: string;
|
|
788
|
-
/** The agent loop — pass @odla-ai/ai's `runAgent`. */
|
|
789
1367
|
runAgent: (inference: Inference, persona: Persona, input: AgentRunInput) => Promise<{
|
|
790
1368
|
finalText: string;
|
|
791
1369
|
}>;
|
|
792
|
-
|
|
793
|
-
fileBaseUrl: string;
|
|
794
|
-
/** Optional chat-skill factory (e.g. wrapping @odla-ai/chat's chatSkill) so
|
|
795
|
-
* the bot can reply in the triggering channel. */
|
|
1370
|
+
newId?: () => string;
|
|
796
1371
|
chatSkillFor?: (channelId: string, self: BrandSkillSelf) => Skill;
|
|
797
|
-
/** Model catalog slice (model id → capability spec) for the vision probe;
|
|
798
|
-
* an absent catalog or unknown model fails safe to the pre-turn path. */
|
|
799
1372
|
catalog?: Record<string, BrandVisionSpec>;
|
|
800
1373
|
}
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
*
|
|
809
|
-
|
|
810
|
-
|
|
1374
|
+
|
|
1375
|
+
/** Reload message attachment ids against the exact live linked Brand book. */
|
|
1376
|
+
declare function attachedBrandAssetIds(db: BrandDb, book: BrandBook, row: Record<string, unknown>): Promise<string[]>;
|
|
1377
|
+
|
|
1378
|
+
/** Strict-enough structural parse for the signed host dispatch envelope. */
|
|
1379
|
+
declare function parseBrandDispatch(raw: unknown): BrandDispatchBody | null;
|
|
1380
|
+
/** Channel ids are unique by schema, but ambiguity still fails closed if a
|
|
1381
|
+
* legacy/corrupt store returns more than one row. */
|
|
1382
|
+
declare function bookForChannel(db: BrandDb, channelId: string): Promise<BrandBook | null>;
|
|
1383
|
+
/** Assemble the conversational request. Attachments remain supported as a
|
|
1384
|
+
* pure helper, but secure dispatch does not pass signed/private URLs here. */
|
|
1385
|
+
declare function brandInputFor(body: BrandDispatchBody, attachments?: ImageBlock[], author?: BrandPrincipalProjection, attachedAssetIds?: readonly string[]): string | OracleContentBlock[];
|
|
1386
|
+
/** Preflight exact app/skill/channel/roster/live brand.read before the model
|
|
1387
|
+
* is invoked. Every tool revalidates its own read/edit capability as well. */
|
|
811
1388
|
declare function dispatchBrandTurn(deps: BrandDispatchDeps, body: BrandDispatchBody): Promise<{
|
|
812
1389
|
finalText: string;
|
|
1390
|
+
durableOutcome: boolean;
|
|
813
1391
|
}>;
|
|
814
1392
|
|
|
815
1393
|
/** The odla-db namespace chat messages live in.
|
|
@@ -901,6 +1479,8 @@ interface BrandIntegrationDescriptor {
|
|
|
901
1479
|
rules: BrandRules;
|
|
902
1480
|
/** Commit triggers to register at /app/:id/admin/triggers (per-bot; app-supplied). */
|
|
903
1481
|
triggers: BrandTrigger[];
|
|
1482
|
+
/** Least-privilege agent capabilities and semantic-operation boundary. */
|
|
1483
|
+
agentProfile: BrandAgentProfile;
|
|
904
1484
|
probes?: BrandIntegrationProbe[];
|
|
905
1485
|
provision: IntegrationProvision;
|
|
906
1486
|
}
|
|
@@ -933,4 +1513,4 @@ interface CreateBrandIntegrationOptions {
|
|
|
933
1513
|
*/
|
|
934
1514
|
declare function createBrandIntegration(options?: CreateBrandIntegrationOptions): BrandIntegrationDescriptor;
|
|
935
1515
|
|
|
936
|
-
export { ASSET_CONTENT_TYPES, type AcceptProposalInput, AssetAnalysis, AssetKind, type AttrType, type AudienceChildren, BRAND_INSTRUCTIONS, BRAND_RULES, BRAND_SCHEMA, BrandActor, BrandBook, type BrandBotTriggerOpts, BrandDb, type BrandDeps, type BrandDispatchBody, type BrandDispatchDeps, BrandEntityRef, type BrandFetchedBytes, BrandInputError, type BrandIntegrationDescriptor, type BrandIntegrationProbe, BrandNotFoundError, BrandOp, BrandProposal, type BrandRouteCtx, type BrandRouteOpts, type BrandRule, type BrandRules, type BrandSkillOpts, type BrandSkillSelf, type BrandToolCtx, type BrandTrigger, type BrandVisionCapabilities, type BrandVisionSpec, CHART_DELTA_MIN, CHAT_MESSAGE_NS, CSS_NAMED_COLORS, type ContrastKind, type CreateAssetInput, type CreateBookInput, type CreateBrandIntegrationOptions, type CreateBrandPersonaOpts, DEFAULT_BRAND_SYSTEM, type DeriveChartOptions, type DerivePaletteOptions, type Hsl, type IntegrationProvision, type IntegrationSecret, type IntegrationSetting, type LightnessDirection, MAX_SWATCHES, MAX_VIEW_BYTES, type NamedColor, type NearestNamedColor, type Oklab, type Oklch, PICK_TEXT_DEFAULT_CANDIDATES, type ProposePaletteInput, RAMP_L_MAX, RAMP_L_MIN, type RejectProposalInput, type ResolvedBrandDeps, type Rgb, SectionKind, SectionStatus, type SerializedAttr, type SerializedEntity, type SerializedLink, type SerializedLinkEnd, type SerializedSchema, Swatch, type UpsertSectionInput, acceptProposalOps, adjustLightnessUntil, analogous, assertAnalysis, assertAssetContentType, assertHex, assertSectionContent, assertSwatches, assetTools, audienceFanoutOps, base64FromBytes, bookForChannel, bookTools, brandBotTrigger, brandInputFor, brandIntegration, brandRules, brandSkill, capString, capStringArray, clamp01, clampToGamut, complementary, contrastRatio, createAssetOps, createBookOps, createBrandIntegration, createBrandPersona, createBrandRoutes, deltaEOK, deltaEOKLab, deriveChartColors, derivePalette, dispatchBrandTurn, hexToOklch, hslToRgb, inSrgbGamut, linearToSrgb, meetsAA, meetsAAA, monochrome, nearestNamedColor, normalizeHex, oklabToOklch, oklabToRgb, oklchToHex, oklchToOklab, paletteTools, parseBrandDispatch, parseHex, pickTextOn, proposePaletteOps, readTools, recordAnalysisOps, rejectProposalOps, relativeLuminance, resolveDeps, rgbToHsl, rgbToOklab, rotateHue, safeFileName, sectionKey, splitComplementary, srgbToLinear, supportsBrandVision, tetradic, tintShadeRamp, toHex,
|
|
1516
|
+
export { ASSET_CONTENT_TYPES, type AcceptProposalInput, AssetAnalysis, AssetKind, type AttrType, type AudienceChildren, BRAND_AGENT_PROFILE, BRAND_DISCUSSION_REFERENCE_KINDS, BRAND_INSTRUCTIONS, BRAND_RULES, BRAND_SCHEMA, BookStatus, type BrandActor, type BrandAgentBridge, type BrandAgentProfile, type BrandApprovalReceipt, type BrandAsset, type BrandAttrs, type BrandBook, type BrandBotTriggerOpts, type BrandCapabilityAuthority, BrandConflictError, type BrandDb, type BrandDecisionBinding, type BrandDeps, type BrandDiscussionReference, type BrandDiscussionReferenceKind, type BrandDiscussionReferenceTarget, type BrandDispatchBody, type BrandDispatchDeps, type BrandEntityRef, type BrandFetchedBytes, type BrandFileRecord, BrandForbiddenError, BrandGoneError, type BrandHumanAuthorityConsumption, BrandInputError, type BrandIntegrationDescriptor, type BrandIntegrationProbe, type BrandLookup, BrandNotFoundError, type BrandOp, type BrandPalette, type BrandPrincipalProjection, type BrandProposal, type BrandProposalProvenance, type BrandProposalReviewSnapshot, type BrandResult, BrandReviewStateChangedError, type BrandRouteCtx, type BrandRouteOpts, type BrandRow, type BrandRule, type BrandRules, type BrandScalar, type BrandSection, type BrandSkillOpts, type BrandSkillSelf, type BrandSourceAssetSnapshot, type BrandStorage, BrandTokensSnapshot, type BrandToolCtx, type BrandTransactGuard, type BrandTransactOptions, type BrandTrigger, type BrandUploadBody, type BrandVisionCapabilities, type BrandVisionSpec, CHART_DELTA_MIN, CHAT_MESSAGE_NS, CSS_NAMED_COLORS, type ContrastKind, type CreateAssetInput, type CreateBookInput, type CreateBrandIntegrationOptions, type CreateBrandPersonaOpts, DEFAULT_BRAND_SYSTEM, type DeriveChartOptions, type DerivePaletteOptions, type Hsl, type IntegrationProvision, type IntegrationSecret, type IntegrationSetting, type LightnessDirection, MAX_SWATCHES, MAX_VIEW_BYTES, type NamedColor, type NearestNamedColor, type Oklab, type Oklch, PICK_TEXT_DEFAULT_CANDIDATES, PaletteSource, PaletteStatus, ProposalKind, ProposalStatus, type ProposePaletteInput, type ProposeSectionInput, RAMP_L_MAX, RAMP_L_MIN, type RejectProposalInput, type ResolvedBrandDeps, type Rgb, SectionKind, SectionStatus, type SerializedAttr, type SerializedEntity, type SerializedLink, type SerializedLinkEnd, type SerializedSchema, Swatch, type UpsertSectionInput, acceptProposalOps, adjustLightnessUntil, analogous, assertAnalysis, assertAssetContentType, assertHex, assertSectionContent, assertSwatches, assetTools, attachedBrandAssetIds, audienceFanoutOps, base64FromBytes, beginAssetDeleteOps, bookForChannel, bookTools, brandAuthorityRef, brandBotTrigger, brandDiscussionReferenceHref, brandDiscussionReferenceId, brandInputFor, brandIntegration, brandJsonDigest, brandRules, brandSkill, canonicalBrandJson, capString, capStringArray, clamp01, clampToGamut, complementary, contrastRatio, createAssetOps, createBookOps, createBrandIntegration, createBrandPersona, createBrandRoutes, deltaEOK, deltaEOKLab, deriveChartColors, derivePalette, dispatchBrandTurn, finishAssetDeleteOps, formatBrandDiscussionReference, hexToOklch, hslToRgb, inSrgbGamut, isBoundedBrandJson, isBrandHumanAuthorityConsumption, linearToSrgb, meetsAA, meetsAAA, monochrome, nearestNamedColor, normalizeHex, oklabToOklch, oklabToRgb, oklchToHex, oklchToOklab, paletteTools, parseBrandDiscussionReference, parseBrandDispatch, parseHex, pickTextOn, proposalReviewSnapshot, proposePaletteOps, proposeSectionOps, readTools, recordAnalysisOps, rejectProposalOps, relativeLuminance, resolveDeps, rgbToHsl, rgbToOklab, rotateHue, safeFileName, sectionKey, splitComplementary, srgbToLinear, supportsBrandVision, tetradic, tintShadeRamp, toHex, triadic, updateBookOps, upsertSectionOps, verifyBrandApprovalReceipt };
|