@odla-ai/brand 0.2.1 → 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/README.md +123 -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 +2242 -332
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +671 -76
- package/dist/index.d.ts +671 -76
- package/dist/index.js +2243 -333
- 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.cts
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.cjs';
|
|
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.cjs';
|
|
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,75 @@ 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
|
+
/** Bounded color projection shared with Discussion people and agents. */
|
|
538
|
+
interface BrandDiscussionSwatch {
|
|
539
|
+
/** Semantic role used by the Brand token compiler. */
|
|
540
|
+
role: string;
|
|
541
|
+
/** Normalized opaque sRGB color (`#rrggbb`). */
|
|
542
|
+
hex: string;
|
|
543
|
+
/** Optional product-authored color name. */
|
|
544
|
+
name?: string;
|
|
545
|
+
}
|
|
546
|
+
/** Product-owned projection returned to Discussion typeahead and exact lookup. */
|
|
547
|
+
interface BrandDiscussionReference {
|
|
548
|
+
/** Canonical Brand kind used in stored Discussion ref markup. */
|
|
549
|
+
kind: BrandDiscussionReferenceKind;
|
|
550
|
+
/** Opaque durable product id; never infer membership from its segments. */
|
|
551
|
+
id: string;
|
|
552
|
+
/** Product-authored primary display name. */
|
|
553
|
+
label: string;
|
|
554
|
+
/** Short product-authored secondary context for the picker. */
|
|
555
|
+
hint: string;
|
|
556
|
+
/** Bounded product-authored context safe to show an LLM or person. */
|
|
557
|
+
summary: string;
|
|
558
|
+
/** Current product status at inspection time. */
|
|
559
|
+
status: string;
|
|
560
|
+
/** Human-readable native surface the link opens. */
|
|
561
|
+
destination: string;
|
|
562
|
+
/** Same-origin native link; navigation is not mutation authority. */
|
|
563
|
+
href: string;
|
|
564
|
+
/** Present only for a validated Brand palette, capped by Brand's swatch limit. */
|
|
565
|
+
swatches?: BrandDiscussionSwatch[];
|
|
566
|
+
}
|
|
567
|
+
/** Durable ref id: a book id, or `bookId/resourceId` for a child resource. */
|
|
568
|
+
declare function brandDiscussionReferenceId(target: BrandDiscussionReferenceTarget): string;
|
|
569
|
+
/** Canonical value stored in the stable `odla-ref` query parameter. */
|
|
570
|
+
declare function formatBrandDiscussionReference(target: BrandDiscussionReferenceTarget): string;
|
|
571
|
+
/** Parse and validate a Brand `odla-ref`; malformed and cross-product refs fail closed. */
|
|
572
|
+
declare function parseBrandDiscussionReference(input: URL | string): BrandDiscussionReferenceTarget | null;
|
|
573
|
+
/** Build the native Brand deep link while preserving the deployed origin. */
|
|
574
|
+
declare function brandDiscussionReferenceHref(current: URL, target: BrandDiscussionReferenceTarget, basePath?: string): string;
|
|
575
|
+
|
|
154
576
|
/** Input to {@link createBookOps}. `memberIds` is the full auth roster —
|
|
155
577
|
* include the bot agent's id so it can pass the audience rules. */
|
|
156
578
|
interface CreateBookInput {
|
|
@@ -158,6 +580,7 @@ interface CreateBookInput {
|
|
|
158
580
|
slug: string;
|
|
159
581
|
name: string;
|
|
160
582
|
ownerId: string;
|
|
583
|
+
createdAuthorityRef: string;
|
|
161
584
|
memberIds: string[];
|
|
162
585
|
channelId?: string;
|
|
163
586
|
now: number;
|
|
@@ -212,6 +635,8 @@ interface UpsertSectionInput {
|
|
|
212
635
|
audience: string[];
|
|
213
636
|
updatedBy: string;
|
|
214
637
|
now: number;
|
|
638
|
+
approvalReceiptId?: string;
|
|
639
|
+
approvalActionDigest?: string;
|
|
215
640
|
}
|
|
216
641
|
/**
|
|
217
642
|
* Ops to create-or-replace a book's section of one kind: a single `update`
|
|
@@ -220,6 +645,24 @@ interface UpsertSectionInput {
|
|
|
220
645
|
* snapshot, and the author/timestamp.
|
|
221
646
|
*/
|
|
222
647
|
declare function upsertSectionOps(input: UpsertSectionInput): BrandOp[];
|
|
648
|
+
/** Input for an agent-authored non-palette facet proposal. */
|
|
649
|
+
interface ProposeSectionInput {
|
|
650
|
+
id: string;
|
|
651
|
+
bookId: string;
|
|
652
|
+
kind: Exclude<SectionKind, "palette">;
|
|
653
|
+
content: Record<string, unknown>;
|
|
654
|
+
rationale: string;
|
|
655
|
+
audience: string[];
|
|
656
|
+
createdBy: string;
|
|
657
|
+
createdAuthorityRef: string;
|
|
658
|
+
sourceAsset?: BrandProposal["provenance"]["sourceAsset"];
|
|
659
|
+
messageId: string;
|
|
660
|
+
turnId: string;
|
|
661
|
+
taintLabels: string[];
|
|
662
|
+
now: number;
|
|
663
|
+
}
|
|
664
|
+
/** Validate a facet draft and park it as an immutable OPEN proposal. */
|
|
665
|
+
declare function proposeSectionOps(input: ProposeSectionInput): Promise<BrandOp[]>;
|
|
223
666
|
|
|
224
667
|
/** Input to {@link proposePaletteOps}. `audience` is the book's roster
|
|
225
668
|
* snapshot; `contrastReport` is stored verbatim in the payload for the
|
|
@@ -233,9 +676,12 @@ interface ProposePaletteInput {
|
|
|
233
676
|
seedHex?: string;
|
|
234
677
|
contrastReport?: unknown;
|
|
235
678
|
createdBy: string;
|
|
679
|
+
createdAuthorityRef: string;
|
|
236
680
|
audience: string[];
|
|
237
|
-
|
|
238
|
-
messageId
|
|
681
|
+
sourceAsset?: BrandProposal["provenance"]["sourceAsset"];
|
|
682
|
+
messageId: string;
|
|
683
|
+
turnId: string;
|
|
684
|
+
taintLabels: string[];
|
|
239
685
|
now: number;
|
|
240
686
|
}
|
|
241
687
|
/**
|
|
@@ -243,13 +689,15 @@ interface ProposePaletteInput {
|
|
|
243
689
|
* `kind: "palette"`, `status: "open"`, with the validated swatches (and
|
|
244
690
|
* optional seed/contrast report) in `payload`.
|
|
245
691
|
*/
|
|
246
|
-
declare function proposePaletteOps(input: ProposePaletteInput): BrandOp[]
|
|
692
|
+
declare function proposePaletteOps(input: ProposePaletteInput): Promise<BrandOp[]>;
|
|
247
693
|
/** Input to {@link acceptProposalOps}: the proposal row as read back, the id
|
|
248
694
|
* to mint the palette under, and who resolved it. */
|
|
249
695
|
interface AcceptProposalInput {
|
|
250
696
|
proposal: BrandProposal;
|
|
251
697
|
paletteId: string;
|
|
252
698
|
resolvedBy: string;
|
|
699
|
+
approvalReceiptId: string;
|
|
700
|
+
approvalActionDigest: string;
|
|
253
701
|
now: number;
|
|
254
702
|
resolutionNote?: string;
|
|
255
703
|
}
|
|
@@ -279,16 +727,18 @@ interface RejectProposalInput {
|
|
|
279
727
|
declare function rejectProposalOps(input: RejectProposalInput): BrandOp[];
|
|
280
728
|
|
|
281
729
|
/** Input to {@link createAssetOps} — the storage upload's receipt fields
|
|
282
|
-
* (`path`/`
|
|
730
|
+
* (`path`/`size`) plus the declared kind and the book's audience. */
|
|
283
731
|
interface CreateAssetInput {
|
|
284
732
|
id: string;
|
|
285
733
|
bookId: string;
|
|
286
734
|
kind: AssetKind;
|
|
287
735
|
path: string;
|
|
288
|
-
|
|
736
|
+
storageObjectId: string;
|
|
737
|
+
contentDigest: string;
|
|
289
738
|
contentType: string;
|
|
290
739
|
size: number;
|
|
291
740
|
uploadedBy: string;
|
|
741
|
+
uploadedAuthorityRef: string;
|
|
292
742
|
audience: string[];
|
|
293
743
|
title?: string;
|
|
294
744
|
now: number;
|
|
@@ -304,12 +754,14 @@ declare function createAssetOps(input: CreateAssetInput): BrandOp[];
|
|
|
304
754
|
* `deletedAt` in place. List reads exclude tombstoned rows; the row itself
|
|
305
755
|
* stays for provenance.
|
|
306
756
|
*/
|
|
307
|
-
declare function
|
|
757
|
+
declare function beginAssetDeleteOps(assetId: BrandEntityRef, now: number, deletedBy: string, deletedAuthorityRef: string): BrandOp[];
|
|
758
|
+
/** Complete a previously authorized deletion after storage is tombstoned. */
|
|
759
|
+
declare function finishAssetDeleteOps(assetId: BrandEntityRef): BrandOp[];
|
|
308
760
|
/**
|
|
309
761
|
* Ops to record an agent's analysis of an asset: the validated + capped
|
|
310
762
|
* analysis json plus `analyzedAt`. Replaces any prior analysis whole.
|
|
311
763
|
*/
|
|
312
|
-
declare function recordAnalysisOps(assetId: BrandEntityRef, analysis: unknown, now: number): BrandOp[]
|
|
764
|
+
declare function recordAnalysisOps(assetId: BrandEntityRef, analysis: unknown, priorRevision: number, analyzedBy: string, analyzedAuthorityRef: string, now: number): Promise<BrandOp[]>;
|
|
313
765
|
|
|
314
766
|
/** An sRGB color with channels as fractions in [0, 1]. */
|
|
315
767
|
interface Rgb {
|
|
@@ -566,6 +1018,21 @@ interface DerivePaletteOptions {
|
|
|
566
1018
|
*/
|
|
567
1019
|
declare function derivePalette(seedHex: string, opts?: DerivePaletteOptions): Swatch[];
|
|
568
1020
|
|
|
1021
|
+
/** Semantic Brand capability granted to one live agent principal. */
|
|
1022
|
+
type BrandCapability = "brand.read" | "brand.edit";
|
|
1023
|
+
/** Host-verified evidence that an agent currently holds one Brand capability. */
|
|
1024
|
+
interface BrandCapabilityAuthority {
|
|
1025
|
+
capability: BrandCapability;
|
|
1026
|
+
authorityRef: string;
|
|
1027
|
+
}
|
|
1028
|
+
/** Safe directory projection exposed to an agent for Brand attribution. */
|
|
1029
|
+
interface BrandPrincipalProjection {
|
|
1030
|
+
id: string;
|
|
1031
|
+
displayName: string;
|
|
1032
|
+
kind: "human" | "agent" | "service";
|
|
1033
|
+
managerDisplayName?: string;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
569
1036
|
/** The bot identity the skill writes as (`selfId` = the agent id carried in
|
|
570
1037
|
* the book's `memberIds` roster and every audience snapshot). */
|
|
571
1038
|
interface BrandSkillSelf {
|
|
@@ -573,6 +1040,32 @@ interface BrandSkillSelf {
|
|
|
573
1040
|
kind: "bot";
|
|
574
1041
|
displayName?: string;
|
|
575
1042
|
}
|
|
1043
|
+
/** Server-enforced semantic bridge. Raw agent credentials must be denied all
|
|
1044
|
+
* Brand namespace writes and raw file operations. */
|
|
1045
|
+
interface BrandAgentBridge {
|
|
1046
|
+
createProposal(input: {
|
|
1047
|
+
jobId: string;
|
|
1048
|
+
bookId: string;
|
|
1049
|
+
mutationId: string;
|
|
1050
|
+
kind: ProposalKind;
|
|
1051
|
+
payload: Record<string, unknown>;
|
|
1052
|
+
rationale: string;
|
|
1053
|
+
sourceAssetId?: string;
|
|
1054
|
+
}): Promise<BrandProposal>;
|
|
1055
|
+
recordAssetAnalysis(input: {
|
|
1056
|
+
jobId: string;
|
|
1057
|
+
mutationId: string;
|
|
1058
|
+
bookId: string;
|
|
1059
|
+
assetId: string;
|
|
1060
|
+
analysis: AssetAnalysis;
|
|
1061
|
+
expectedAnalysisRevision: number;
|
|
1062
|
+
}): Promise<BrandAsset>;
|
|
1063
|
+
readAssetContent(input: {
|
|
1064
|
+
jobId: string;
|
|
1065
|
+
bookId: string;
|
|
1066
|
+
assetId: string;
|
|
1067
|
+
}): Promise<BrandFetchedBytes>;
|
|
1068
|
+
}
|
|
576
1069
|
/** Options for {@link brandSkill}. */
|
|
577
1070
|
interface BrandSkillOpts {
|
|
578
1071
|
/** The injected odla client (a real @odla-ai/db AdminDb satisfies it). */
|
|
@@ -581,10 +1074,27 @@ interface BrandSkillOpts {
|
|
|
581
1074
|
bookId: string;
|
|
582
1075
|
/** The bot identity acting through these tools. */
|
|
583
1076
|
self: BrandSkillSelf;
|
|
584
|
-
/**
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
1077
|
+
/** Host attestation for the rules-scoped credential behind `db`. */
|
|
1078
|
+
agentDbBinding: {
|
|
1079
|
+
principalId: string;
|
|
1080
|
+
credentialRef: string;
|
|
1081
|
+
};
|
|
1082
|
+
/** Active verified agent job; the bridge derives message/turn provenance. */
|
|
1083
|
+
agentJobId: string;
|
|
1084
|
+
agentBridge: BrandAgentBridge;
|
|
1085
|
+
/** Host verification against the live principal grant. Missing/denied hooks
|
|
1086
|
+
* fail closed; roster membership is visibility, not authority. */
|
|
1087
|
+
authorizeCapability: (input: {
|
|
1088
|
+
agentId: string;
|
|
1089
|
+
bookId: string;
|
|
1090
|
+
capability: BrandCapability;
|
|
1091
|
+
}) => Promise<BrandCapabilityAuthority | null> | BrandCapabilityAuthority | null;
|
|
1092
|
+
/** Bounded host directory projection for conversational display only. */
|
|
1093
|
+
resolvePrincipals: (input: {
|
|
1094
|
+
requesterAgentId: string;
|
|
1095
|
+
bookId: string;
|
|
1096
|
+
principalIds: string[];
|
|
1097
|
+
}) => Promise<BrandPrincipalProjection[]>;
|
|
588
1098
|
/** False when the model cannot take image/document blocks inside a
|
|
589
1099
|
* tool_result — view_asset then steers to the pre-turn attachment path. */
|
|
590
1100
|
visionInToolResults?: boolean;
|
|
@@ -598,12 +1108,27 @@ interface BrandToolCtx {
|
|
|
598
1108
|
db: BrandDb;
|
|
599
1109
|
bookId: string;
|
|
600
1110
|
self: BrandSkillSelf;
|
|
601
|
-
fileBaseUrl: string;
|
|
602
|
-
fetchBytes: (url: string) => Promise<BrandFetchedBytes>;
|
|
603
1111
|
/** Whether image/document blocks may be returned inside tool results. */
|
|
604
1112
|
visionInToolResults: boolean;
|
|
605
1113
|
now: () => number;
|
|
606
1114
|
newId: () => string;
|
|
1115
|
+
agentJobId: string;
|
|
1116
|
+
createProposal(input: {
|
|
1117
|
+
mutationId: string;
|
|
1118
|
+
kind: ProposalKind;
|
|
1119
|
+
payload: Record<string, unknown>;
|
|
1120
|
+
rationale: string;
|
|
1121
|
+
sourceAssetId?: string;
|
|
1122
|
+
}): Promise<BrandProposal>;
|
|
1123
|
+
recordAssetAnalysis(input: {
|
|
1124
|
+
mutationId: string;
|
|
1125
|
+
assetId: string;
|
|
1126
|
+
analysis: AssetAnalysis;
|
|
1127
|
+
expectedAnalysisRevision: number;
|
|
1128
|
+
}): Promise<BrandAsset>;
|
|
1129
|
+
readAssetContent(assetId: string): Promise<BrandFetchedBytes>;
|
|
1130
|
+
resolvePrincipals(ids: string[]): Promise<BrandPrincipalProjection[]>;
|
|
1131
|
+
authority(capability: BrandCapability): Promise<BrandCapabilityAuthority>;
|
|
607
1132
|
/** Load the scoped book row; throws BrandNotFoundError when missing. */
|
|
608
1133
|
loadBook(): Promise<BrandBook>;
|
|
609
1134
|
/** Wrap a handler so Brand validation errors come back as actionable
|
|
@@ -638,17 +1163,13 @@ declare function base64FromBytes(bytes: Uint8Array): string;
|
|
|
638
1163
|
*/
|
|
639
1164
|
declare function assetTools(ctx: BrandToolCtx): ToolDef[];
|
|
640
1165
|
|
|
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
|
-
*/
|
|
1166
|
+
/** `update_section` validates a draft and parks it as an OPEN proposal. */
|
|
646
1167
|
declare function bookTools(ctx: BrandToolCtx): ToolDef[];
|
|
647
1168
|
|
|
648
1169
|
/**
|
|
649
1170
|
* The palette tools: `analyze_color`, `evaluate_contrast` (pure math),
|
|
650
1171
|
* `propose_palette` (writes an OPEN proposal with an automatic contrast
|
|
651
|
-
* report)
|
|
1172
|
+
* report). Resolution is deliberately not an agent tool.
|
|
652
1173
|
*/
|
|
653
1174
|
declare function paletteTools(ctx: BrandToolCtx): ToolDef[];
|
|
654
1175
|
|
|
@@ -699,15 +1220,76 @@ declare function supportsBrandVision(spec: BrandVisionSpec | null | undefined):
|
|
|
699
1220
|
*/
|
|
700
1221
|
declare function readTools(ctx: BrandToolCtx): ToolDef[];
|
|
701
1222
|
|
|
1223
|
+
type BrandRouteCapability = "brand.edit" | "app.manage";
|
|
1224
|
+
type BrandRouteEffect = "internal" | "destructive";
|
|
1225
|
+
interface BrandRouteAuthority {
|
|
1226
|
+
authorityRef: string;
|
|
1227
|
+
actorPrincipalId: string;
|
|
1228
|
+
capability: BrandRouteCapability;
|
|
1229
|
+
effect: BrandRouteEffect;
|
|
1230
|
+
}
|
|
702
1231
|
/** Everything {@link import("./index").createBrandRoutes} needs from the host worker. */
|
|
703
1232
|
interface BrandRouteOpts {
|
|
704
1233
|
/** The injected odla client (a real @odla-ai/db AdminDb satisfies it). */
|
|
705
1234
|
db: BrandDb;
|
|
1235
|
+
/** Registry app that owns the book rows and central authority records. */
|
|
1236
|
+
appId: string;
|
|
706
1237
|
/** Host-owned auth: resolve the request to an actor or null (→ 401). The
|
|
707
1238
|
* tokens routes skip this only when `publicTokens` is true. */
|
|
708
1239
|
authorize: (req: Request) => Promise<BrandActor | null> | BrandActor | null;
|
|
1240
|
+
/** Optional host-owned authority seam for read-only Discussion reference
|
|
1241
|
+
* lookup. Verify exact Brand product, brand.read capability, canonical
|
|
1242
|
+
* audience, principal, current app lifetime/environment, and agent grant
|
|
1243
|
+
* provenance here; when omitted, the ordinary request authorizer is used. */
|
|
1244
|
+
authorizeDiscussionReferences?: (req: Request) => Promise<BrandActor | null> | BrandActor | null;
|
|
1245
|
+
/** Live host verification for worker-mediated effects. The callback must
|
|
1246
|
+
* verify the direct human credential, current app owner/co-owner status,
|
|
1247
|
+
* exact capability/effect/resource, and return null on any uncertainty. */
|
|
1248
|
+
authorizeCapability: (input: {
|
|
1249
|
+
req: Request;
|
|
1250
|
+
actor: BrandActor;
|
|
1251
|
+
appId: string;
|
|
1252
|
+
bookId?: string;
|
|
1253
|
+
capability: BrandRouteCapability;
|
|
1254
|
+
effect: BrandRouteEffect;
|
|
1255
|
+
}) => Promise<BrandRouteAuthority | null> | BrandRouteAuthority | null;
|
|
1256
|
+
/** Consume or idempotently replay one registry `human_exact` authority use,
|
|
1257
|
+
* then reload and authenticate its immutable central receipt. Missing,
|
|
1258
|
+
* synthetic, cached, or unverifiable authority must return null. */
|
|
1259
|
+
consumeHumanExact: (input: {
|
|
1260
|
+
req: Request;
|
|
1261
|
+
actor: BrandActor;
|
|
1262
|
+
appId: string;
|
|
1263
|
+
capability: "brand.proposal.resolve";
|
|
1264
|
+
projectCapability: "brand.approve";
|
|
1265
|
+
effect: "internal";
|
|
1266
|
+
resource: {
|
|
1267
|
+
bookId: string;
|
|
1268
|
+
proposalId: string;
|
|
1269
|
+
};
|
|
1270
|
+
actionDigest: string;
|
|
1271
|
+
consumptionIdempotencyKey: string;
|
|
1272
|
+
}) => Promise<BrandHumanAuthorityConsumption | null> | BrandHumanAuthorityConsumption | null;
|
|
1273
|
+
/** Re-read the private object and authenticate the exact snapshot captured
|
|
1274
|
+
* by the agent bridge. This must verify path, ETag, size, and SHA-256 bytes;
|
|
1275
|
+
* returning false prevents authority consumption and the local effect. */
|
|
1276
|
+
verifySourceAssetSnapshot: (input: {
|
|
1277
|
+
req: Request;
|
|
1278
|
+
appId: string;
|
|
1279
|
+
bookId: string;
|
|
1280
|
+
assetId: string;
|
|
1281
|
+
path: string;
|
|
1282
|
+
snapshot: BrandSourceAssetSnapshot;
|
|
1283
|
+
}) => Promise<boolean> | boolean;
|
|
709
1284
|
/** Mount point. Default "/api/brand". */
|
|
710
1285
|
basePath?: string;
|
|
1286
|
+
/** Native UI mount used by returned Discussion deep links. Default "/". */
|
|
1287
|
+
discussionBasePath?: string;
|
|
1288
|
+
/**
|
|
1289
|
+
* Product-owned fetch used only for a short-lived URL minted from a linked
|
|
1290
|
+
* private Brand asset. Callers never provide this URL or receive it back.
|
|
1291
|
+
*/
|
|
1292
|
+
fetchPrivateAsset?: typeof fetch;
|
|
711
1293
|
/** Upload size cap in bytes (checked against `File.size`). Default 8 MiB. */
|
|
712
1294
|
maxUploadBytes?: number;
|
|
713
1295
|
/** Serve `GET /books/:id/tokens.css` and `tokens.json` without authorize —
|
|
@@ -721,12 +1303,21 @@ interface BrandRouteOpts {
|
|
|
721
1303
|
/** Per-request context handed to the authorized route handlers. */
|
|
722
1304
|
interface BrandRouteCtx {
|
|
723
1305
|
db: BrandDb;
|
|
1306
|
+
appId: string;
|
|
724
1307
|
actor: BrandActor;
|
|
1308
|
+
authorizeCapability: BrandRouteOpts["authorizeCapability"];
|
|
1309
|
+
consumeHumanExact: BrandRouteOpts["consumeHumanExact"];
|
|
1310
|
+
verifySourceAssetSnapshot: BrandRouteOpts["verifySourceAssetSnapshot"];
|
|
725
1311
|
now: () => number;
|
|
726
1312
|
newId: () => string;
|
|
727
1313
|
maxUploadBytes: number;
|
|
1314
|
+
discussionBasePath: string;
|
|
1315
|
+
fetchPrivateAsset: typeof fetch;
|
|
728
1316
|
}
|
|
729
1317
|
|
|
1318
|
+
/** Freeze the exact OPEN proposal fields a reviewer sees. */
|
|
1319
|
+
declare function proposalReviewSnapshot(proposal: BrandProposal): BrandProposalReviewSnapshot;
|
|
1320
|
+
|
|
730
1321
|
/**
|
|
731
1322
|
* Build the brand fetch handler. Returns `null` for requests outside
|
|
732
1323
|
* `basePath` (default `/api/brand`) so the host worker falls through to its
|
|
@@ -737,11 +1328,13 @@ interface BrandRouteCtx {
|
|
|
737
1328
|
*/
|
|
738
1329
|
declare function createBrandRoutes(options: BrandRouteOpts): (req: Request) => Promise<Response | null>;
|
|
739
1330
|
|
|
740
|
-
/**
|
|
741
|
-
* the same wire shape chat-agent consumes (see the header provenance note). */
|
|
1331
|
+
/** Versioned, host-authenticated envelope for one Brand agent turn. */
|
|
742
1332
|
interface BrandDispatchBody {
|
|
743
|
-
v:
|
|
1333
|
+
v: 2;
|
|
744
1334
|
appId: string;
|
|
1335
|
+
/** Exact Registry app lifetime admitted by the durable Server job. */
|
|
1336
|
+
appIncarnation: string;
|
|
1337
|
+
jobId: string;
|
|
745
1338
|
trigger: {
|
|
746
1339
|
id: string;
|
|
747
1340
|
skill: string;
|
|
@@ -757,61 +1350,61 @@ interface BrandDispatchBody {
|
|
|
757
1350
|
row: Record<string, unknown>;
|
|
758
1351
|
};
|
|
759
1352
|
}
|
|
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. */
|
|
1353
|
+
/** Trusted host seams required to run one capability-bound Brand agent turn. */
|
|
781
1354
|
interface BrandDispatchDeps {
|
|
782
|
-
/**
|
|
1355
|
+
/** Service read client; never handed to agent tools. */
|
|
783
1356
|
db: BrandDb;
|
|
784
|
-
|
|
1357
|
+
appId: string;
|
|
1358
|
+
/** Host-created runtime bound to this verified dispatch + exact agent. */
|
|
1359
|
+
agentRuntimeFor: (input: {
|
|
1360
|
+
appId: string;
|
|
1361
|
+
agentId: string;
|
|
1362
|
+
bookId: string;
|
|
1363
|
+
triggerId: string;
|
|
1364
|
+
eventId: string;
|
|
1365
|
+
jobId: string;
|
|
1366
|
+
}) => Promise<{
|
|
1367
|
+
db: BrandDb;
|
|
1368
|
+
credentialRef: string;
|
|
1369
|
+
jobId: string;
|
|
1370
|
+
bridge: BrandAgentBridge;
|
|
1371
|
+
}>;
|
|
1372
|
+
authorizeCapability: (input: {
|
|
1373
|
+
agentId: string;
|
|
1374
|
+
bookId: string;
|
|
1375
|
+
capability: "brand.read" | "brand.edit";
|
|
1376
|
+
}) => Promise<BrandCapabilityAuthority | null> | BrandCapabilityAuthority | null;
|
|
1377
|
+
resolvePrincipals: (input: {
|
|
1378
|
+
requesterAgentId: string;
|
|
1379
|
+
bookId: string;
|
|
1380
|
+
principalIds: string[];
|
|
1381
|
+
}) => Promise<BrandPrincipalProjection[]>;
|
|
785
1382
|
inference: Inference;
|
|
786
|
-
/** Canonical model id for the persona. */
|
|
787
1383
|
model: string;
|
|
788
|
-
/** The agent loop — pass @odla-ai/ai's `runAgent`. */
|
|
789
1384
|
runAgent: (inference: Inference, persona: Persona, input: AgentRunInput) => Promise<{
|
|
790
1385
|
finalText: string;
|
|
791
1386
|
}>;
|
|
792
|
-
/** Origin prefixed onto relative asset urls (skill + pre-turn attachments). */
|
|
793
|
-
fileBaseUrl: string;
|
|
794
|
-
/** Optional stable id factory for durable whole-turn retries. */
|
|
795
1387
|
newId?: () => string;
|
|
796
|
-
/** Optional chat-skill factory (e.g. wrapping @odla-ai/chat's chatSkill) so
|
|
797
|
-
* the bot can reply in the triggering channel. */
|
|
798
1388
|
chatSkillFor?: (channelId: string, self: BrandSkillSelf) => Skill;
|
|
799
|
-
/** Model catalog slice (model id → capability spec) for the vision probe;
|
|
800
|
-
* an absent catalog or unknown model fails safe to the pre-turn path. */
|
|
801
1389
|
catalog?: Record<string, BrandVisionSpec>;
|
|
802
1390
|
}
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
*
|
|
811
|
-
|
|
812
|
-
|
|
1391
|
+
|
|
1392
|
+
/** Reload message attachment ids against the exact live linked Brand book. */
|
|
1393
|
+
declare function attachedBrandAssetIds(db: BrandDb, book: BrandBook, row: Record<string, unknown>): Promise<string[]>;
|
|
1394
|
+
|
|
1395
|
+
/** Strict-enough structural parse for the signed host dispatch envelope. */
|
|
1396
|
+
declare function parseBrandDispatch(raw: unknown): BrandDispatchBody | null;
|
|
1397
|
+
/** Channel ids are unique by schema, but ambiguity still fails closed if a
|
|
1398
|
+
* legacy/corrupt store returns more than one row. */
|
|
1399
|
+
declare function bookForChannel(db: BrandDb, channelId: string): Promise<BrandBook | null>;
|
|
1400
|
+
/** Assemble the conversational request. Attachments remain supported as a
|
|
1401
|
+
* pure helper, but secure dispatch does not pass signed/private URLs here. */
|
|
1402
|
+
declare function brandInputFor(body: BrandDispatchBody, attachments?: ImageBlock[], author?: BrandPrincipalProjection, attachedAssetIds?: readonly string[]): string | OracleContentBlock[];
|
|
1403
|
+
/** Preflight exact app/skill/channel/roster/live brand.read before the model
|
|
1404
|
+
* is invoked. Every tool revalidates its own read/edit capability as well. */
|
|
813
1405
|
declare function dispatchBrandTurn(deps: BrandDispatchDeps, body: BrandDispatchBody): Promise<{
|
|
814
1406
|
finalText: string;
|
|
1407
|
+
durableOutcome: boolean;
|
|
815
1408
|
}>;
|
|
816
1409
|
|
|
817
1410
|
/** The odla-db namespace chat messages live in.
|
|
@@ -903,6 +1496,8 @@ interface BrandIntegrationDescriptor {
|
|
|
903
1496
|
rules: BrandRules;
|
|
904
1497
|
/** Commit triggers to register at /app/:id/admin/triggers (per-bot; app-supplied). */
|
|
905
1498
|
triggers: BrandTrigger[];
|
|
1499
|
+
/** Least-privilege agent capabilities and semantic-operation boundary. */
|
|
1500
|
+
agentProfile: BrandAgentProfile;
|
|
906
1501
|
probes?: BrandIntegrationProbe[];
|
|
907
1502
|
provision: IntegrationProvision;
|
|
908
1503
|
}
|
|
@@ -935,4 +1530,4 @@ interface CreateBrandIntegrationOptions {
|
|
|
935
1530
|
*/
|
|
936
1531
|
declare function createBrandIntegration(options?: CreateBrandIntegrationOptions): BrandIntegrationDescriptor;
|
|
937
1532
|
|
|
938
|
-
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,
|
|
1533
|
+
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 BrandDiscussionSwatch, 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 };
|