@odla-ai/brand 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -0
- package/dist/index.cjs +148 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.js +148 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -534,6 +534,15 @@ interface BrandDiscussionReferenceTarget {
|
|
|
534
534
|
bookId: string;
|
|
535
535
|
resourceId?: string;
|
|
536
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
|
+
}
|
|
537
546
|
/** Product-owned projection returned to Discussion typeahead and exact lookup. */
|
|
538
547
|
interface BrandDiscussionReference {
|
|
539
548
|
/** Canonical Brand kind used in stored Discussion ref markup. */
|
|
@@ -552,6 +561,8 @@ interface BrandDiscussionReference {
|
|
|
552
561
|
destination: string;
|
|
553
562
|
/** Same-origin native link; navigation is not mutation authority. */
|
|
554
563
|
href: string;
|
|
564
|
+
/** Present only for a validated Brand palette, capped by Brand's swatch limit. */
|
|
565
|
+
swatches?: BrandDiscussionSwatch[];
|
|
555
566
|
}
|
|
556
567
|
/** Durable ref id: a book id, or `bookId/resourceId` for a child resource. */
|
|
557
568
|
declare function brandDiscussionReferenceId(target: BrandDiscussionReferenceTarget): string;
|
|
@@ -1274,6 +1285,11 @@ interface BrandRouteOpts {
|
|
|
1274
1285
|
basePath?: string;
|
|
1275
1286
|
/** Native UI mount used by returned Discussion deep links. Default "/". */
|
|
1276
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;
|
|
1277
1293
|
/** Upload size cap in bytes (checked against `File.size`). Default 8 MiB. */
|
|
1278
1294
|
maxUploadBytes?: number;
|
|
1279
1295
|
/** Serve `GET /books/:id/tokens.css` and `tokens.json` without authorize —
|
|
@@ -1296,6 +1312,7 @@ interface BrandRouteCtx {
|
|
|
1296
1312
|
newId: () => string;
|
|
1297
1313
|
maxUploadBytes: number;
|
|
1298
1314
|
discussionBasePath: string;
|
|
1315
|
+
fetchPrivateAsset: typeof fetch;
|
|
1299
1316
|
}
|
|
1300
1317
|
|
|
1301
1318
|
/** Freeze the exact OPEN proposal fields a reviewer sees. */
|
|
@@ -1513,4 +1530,4 @@ interface CreateBrandIntegrationOptions {
|
|
|
1513
1530
|
*/
|
|
1514
1531
|
declare function createBrandIntegration(options?: CreateBrandIntegrationOptions): BrandIntegrationDescriptor;
|
|
1515
1532
|
|
|
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 };
|
|
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -534,6 +534,15 @@ interface BrandDiscussionReferenceTarget {
|
|
|
534
534
|
bookId: string;
|
|
535
535
|
resourceId?: string;
|
|
536
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
|
+
}
|
|
537
546
|
/** Product-owned projection returned to Discussion typeahead and exact lookup. */
|
|
538
547
|
interface BrandDiscussionReference {
|
|
539
548
|
/** Canonical Brand kind used in stored Discussion ref markup. */
|
|
@@ -552,6 +561,8 @@ interface BrandDiscussionReference {
|
|
|
552
561
|
destination: string;
|
|
553
562
|
/** Same-origin native link; navigation is not mutation authority. */
|
|
554
563
|
href: string;
|
|
564
|
+
/** Present only for a validated Brand palette, capped by Brand's swatch limit. */
|
|
565
|
+
swatches?: BrandDiscussionSwatch[];
|
|
555
566
|
}
|
|
556
567
|
/** Durable ref id: a book id, or `bookId/resourceId` for a child resource. */
|
|
557
568
|
declare function brandDiscussionReferenceId(target: BrandDiscussionReferenceTarget): string;
|
|
@@ -1274,6 +1285,11 @@ interface BrandRouteOpts {
|
|
|
1274
1285
|
basePath?: string;
|
|
1275
1286
|
/** Native UI mount used by returned Discussion deep links. Default "/". */
|
|
1276
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;
|
|
1277
1293
|
/** Upload size cap in bytes (checked against `File.size`). Default 8 MiB. */
|
|
1278
1294
|
maxUploadBytes?: number;
|
|
1279
1295
|
/** Serve `GET /books/:id/tokens.css` and `tokens.json` without authorize —
|
|
@@ -1296,6 +1312,7 @@ interface BrandRouteCtx {
|
|
|
1296
1312
|
newId: () => string;
|
|
1297
1313
|
maxUploadBytes: number;
|
|
1298
1314
|
discussionBasePath: string;
|
|
1315
|
+
fetchPrivateAsset: typeof fetch;
|
|
1299
1316
|
}
|
|
1300
1317
|
|
|
1301
1318
|
/** Freeze the exact OPEN proposal fields a reviewer sees. */
|
|
@@ -1513,4 +1530,4 @@ interface CreateBrandIntegrationOptions {
|
|
|
1513
1530
|
*/
|
|
1514
1531
|
declare function createBrandIntegration(options?: CreateBrandIntegrationOptions): BrandIntegrationDescriptor;
|
|
1515
1532
|
|
|
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 };
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -2372,13 +2372,13 @@ async function proposalDecisionOps(input) {
|
|
|
2372
2372
|
|
|
2373
2373
|
// src/routes/proposal-resolution-receipts.ts
|
|
2374
2374
|
async function proposalResolutionMutationKey(bookId, proposalId, mutationId) {
|
|
2375
|
-
const
|
|
2375
|
+
const digest2 = await brandJsonDigest({
|
|
2376
2376
|
version: 3,
|
|
2377
2377
|
bookId,
|
|
2378
2378
|
proposalId,
|
|
2379
2379
|
mutationId
|
|
2380
2380
|
});
|
|
2381
|
-
return `brand:proposal-resolution:v3:${
|
|
2381
|
+
return `brand:proposal-resolution:v3:${digest2.slice("sha256:".length)}`;
|
|
2382
2382
|
}
|
|
2383
2383
|
async function proposalReceiptByMutation(ctx, mutationKey) {
|
|
2384
2384
|
const result = await ctx.db.query({
|
|
@@ -2928,6 +2928,130 @@ async function handleTokens(db, req, bookId, which, actor) {
|
|
|
2928
2928
|
});
|
|
2929
2929
|
}
|
|
2930
2930
|
|
|
2931
|
+
// src/routes/discussion-asset.ts
|
|
2932
|
+
var MAX_DISCUSSION_ASSET_BYTES = 4718592;
|
|
2933
|
+
var SIGN_TTL_SECONDS = 30;
|
|
2934
|
+
var TYPES = /* @__PURE__ */ new Set([
|
|
2935
|
+
"image/png",
|
|
2936
|
+
"image/jpeg",
|
|
2937
|
+
"image/gif",
|
|
2938
|
+
"image/webp",
|
|
2939
|
+
"application/pdf"
|
|
2940
|
+
]);
|
|
2941
|
+
var bare = (value) => (value?.split(";", 1)[0] ?? "").trim().toLowerCase();
|
|
2942
|
+
var starts = (bytes, expected) => expected.every((value, index) => bytes[index] === value);
|
|
2943
|
+
function magicMatches(contentType, bytes) {
|
|
2944
|
+
if (contentType === "image/png") {
|
|
2945
|
+
return starts(bytes, [137, 80, 78, 71, 13, 10, 26, 10]);
|
|
2946
|
+
}
|
|
2947
|
+
if (contentType === "image/jpeg") {
|
|
2948
|
+
return starts(bytes, [255, 216, 255]);
|
|
2949
|
+
}
|
|
2950
|
+
const prefix = new TextDecoder().decode(bytes.subarray(0, 16));
|
|
2951
|
+
if (contentType === "image/gif") {
|
|
2952
|
+
return prefix.startsWith("GIF87a") || prefix.startsWith("GIF89a");
|
|
2953
|
+
}
|
|
2954
|
+
if (contentType === "image/webp") {
|
|
2955
|
+
return prefix.startsWith("RIFF") && prefix.slice(8, 12) === "WEBP";
|
|
2956
|
+
}
|
|
2957
|
+
return contentType === "application/pdf" && prefix.startsWith("%PDF-");
|
|
2958
|
+
}
|
|
2959
|
+
async function boundedBytes(response, max) {
|
|
2960
|
+
const length = Number(response.headers.get("content-length"));
|
|
2961
|
+
if (Number.isFinite(length) && length > max) return null;
|
|
2962
|
+
if (!response.body) return new Uint8Array();
|
|
2963
|
+
const reader = response.body.getReader();
|
|
2964
|
+
const chunks = [];
|
|
2965
|
+
let total = 0;
|
|
2966
|
+
while (true) {
|
|
2967
|
+
const next = await reader.read();
|
|
2968
|
+
if (next.done) break;
|
|
2969
|
+
total += next.value.byteLength;
|
|
2970
|
+
if (total > max) {
|
|
2971
|
+
await reader.cancel();
|
|
2972
|
+
return null;
|
|
2973
|
+
}
|
|
2974
|
+
chunks.push(next.value);
|
|
2975
|
+
}
|
|
2976
|
+
const out = new Uint8Array(total);
|
|
2977
|
+
let offset = 0;
|
|
2978
|
+
for (const chunk of chunks) {
|
|
2979
|
+
out.set(chunk, offset);
|
|
2980
|
+
offset += chunk.byteLength;
|
|
2981
|
+
}
|
|
2982
|
+
return out;
|
|
2983
|
+
}
|
|
2984
|
+
async function digest(bytes) {
|
|
2985
|
+
const value = await crypto.subtle.digest("SHA-256", bytes.slice().buffer);
|
|
2986
|
+
return `sha256:${[...new Uint8Array(value)].map((byte) => byte.toString(16).padStart(2, "0")).join("")}`;
|
|
2987
|
+
}
|
|
2988
|
+
function exactAsset(beforeBook, before, afterBook, after) {
|
|
2989
|
+
return afterBook.id === beforeBook.id && after.id === before.id && after.bookId === before.bookId && after.status === "live" && after.path === before.path && after.storageObjectId === before.storageObjectId && after.contentDigest === before.contentDigest && after.contentType === before.contentType && after.size === before.size;
|
|
2990
|
+
}
|
|
2991
|
+
function safeSignedUrl(value) {
|
|
2992
|
+
try {
|
|
2993
|
+
const url = new URL(value);
|
|
2994
|
+
return value.length <= 4096 && url.protocol === "https:" && !url.username && !url.password ? url : null;
|
|
2995
|
+
} catch {
|
|
2996
|
+
return null;
|
|
2997
|
+
}
|
|
2998
|
+
}
|
|
2999
|
+
async function handleBrandDiscussionAsset(ctx, req, target) {
|
|
3000
|
+
const beforeBook = await loadMemberBook(ctx.db, target.bookId, ctx.actor.id);
|
|
3001
|
+
const before = await linkedAsset(ctx, beforeBook, target.resourceId);
|
|
3002
|
+
const contentType = bare(before.contentType);
|
|
3003
|
+
if (!TYPES.has(contentType)) {
|
|
3004
|
+
return json({ error: "asset content type is not viewable" }, 415);
|
|
3005
|
+
}
|
|
3006
|
+
if (before.size < 1 || before.size > MAX_DISCUSSION_ASSET_BYTES) {
|
|
3007
|
+
return json({ error: "asset exceeds the discussion media limit" }, 413);
|
|
3008
|
+
}
|
|
3009
|
+
const signed = safeSignedUrl(
|
|
3010
|
+
await ctx.db.storage.sign(before.path, SIGN_TTL_SECONDS)
|
|
3011
|
+
);
|
|
3012
|
+
if (!signed) throw new BrandInputError("private asset signing failed");
|
|
3013
|
+
const response = await ctx.fetchPrivateAsset(signed, {
|
|
3014
|
+
headers: { accept: contentType },
|
|
3015
|
+
redirect: "manual",
|
|
3016
|
+
signal: req.signal
|
|
3017
|
+
});
|
|
3018
|
+
if (!response.ok || response.type === "opaqueredirect") {
|
|
3019
|
+
throw new BrandNotFoundError(`asset ${before.id}`);
|
|
3020
|
+
}
|
|
3021
|
+
const served = bare(response.headers.get("content-type"));
|
|
3022
|
+
if (served === "image/svg+xml" || served && served !== "application/octet-stream" && served !== contentType) {
|
|
3023
|
+
return json({ error: "asset content type is inconsistent" }, 415);
|
|
3024
|
+
}
|
|
3025
|
+
const bytes = await boundedBytes(response, MAX_DISCUSSION_ASSET_BYTES);
|
|
3026
|
+
if (!bytes || bytes.byteLength !== before.size || !magicMatches(contentType, bytes) || await digest(bytes) !== before.contentDigest) {
|
|
3027
|
+
return json({ error: "asset bytes failed validation" }, 422);
|
|
3028
|
+
}
|
|
3029
|
+
const afterBook = await loadMemberBook(ctx.db, target.bookId, ctx.actor.id);
|
|
3030
|
+
const after = await linkedAsset(ctx, afterBook, target.resourceId);
|
|
3031
|
+
if (!exactAsset(beforeBook, before, afterBook, after)) {
|
|
3032
|
+
return json({ error: "asset changed during inspection" }, 409);
|
|
3033
|
+
}
|
|
3034
|
+
return json({
|
|
3035
|
+
asset: {
|
|
3036
|
+
reference: { kind: "brand:asset", id: `${before.bookId}/${before.id}` },
|
|
3037
|
+
contentType,
|
|
3038
|
+
byteLength: bytes.byteLength,
|
|
3039
|
+
data: base64(bytes),
|
|
3040
|
+
taint: "untrusted_project_material"
|
|
3041
|
+
}
|
|
3042
|
+
}, 200, {
|
|
3043
|
+
"cache-control": "private, no-store",
|
|
3044
|
+
"x-content-type-options": "nosniff"
|
|
3045
|
+
});
|
|
3046
|
+
}
|
|
3047
|
+
function base64(bytes) {
|
|
3048
|
+
let binary = "";
|
|
3049
|
+
for (let index = 0; index < bytes.length; index += 8192) {
|
|
3050
|
+
binary += String.fromCharCode(...bytes.subarray(index, index + 8192));
|
|
3051
|
+
}
|
|
3052
|
+
return btoa(binary);
|
|
3053
|
+
}
|
|
3054
|
+
|
|
2931
3055
|
// src/routes/discussion-references.ts
|
|
2932
3056
|
var capLimit = (raw) => {
|
|
2933
3057
|
const parsed = Number(raw ?? 20);
|
|
@@ -2959,6 +3083,7 @@ var projection = (req, ctx, book, target, row) => {
|
|
|
2959
3083
|
let summary = `${book.name} brand book`;
|
|
2960
3084
|
let status = book.status;
|
|
2961
3085
|
let destination = "Brand Studio \xB7 Brand book";
|
|
3086
|
+
let swatches;
|
|
2962
3087
|
if (target.kind === "brand:asset") {
|
|
2963
3088
|
const asset = row;
|
|
2964
3089
|
label = asset.title?.trim() || `${asset.kind} asset`;
|
|
@@ -2968,6 +3093,11 @@ var projection = (req, ctx, book, target, row) => {
|
|
|
2968
3093
|
destination = "Brand Studio \xB7 Conversation";
|
|
2969
3094
|
} else if (target.kind === "brand:palette") {
|
|
2970
3095
|
const palette = row;
|
|
3096
|
+
swatches = assertSwatches(palette.swatches).map((swatch) => ({
|
|
3097
|
+
role: swatch.role,
|
|
3098
|
+
hex: swatch.hex,
|
|
3099
|
+
...swatch.name ? { name: swatch.name } : {}
|
|
3100
|
+
}));
|
|
2971
3101
|
label = palette.name;
|
|
2972
3102
|
hint = `${book.name} \xB7 ${palette.status} palette`;
|
|
2973
3103
|
summary = `${palette.swatches.length}-color palette in ${book.name}`;
|
|
@@ -3000,7 +3130,8 @@ var projection = (req, ctx, book, target, row) => {
|
|
|
3000
3130
|
new URL(req.url),
|
|
3001
3131
|
target,
|
|
3002
3132
|
ctx.discussionBasePath
|
|
3003
|
-
)
|
|
3133
|
+
),
|
|
3134
|
+
...swatches ? { swatches } : {}
|
|
3004
3135
|
};
|
|
3005
3136
|
};
|
|
3006
3137
|
async function exact(ctx, req, target) {
|
|
@@ -3054,11 +3185,23 @@ async function search(ctx, req, url) {
|
|
|
3054
3185
|
}
|
|
3055
3186
|
async function handleBrandDiscussionReferences(ctx, req, url) {
|
|
3056
3187
|
if (req.method !== "GET") return methodNotAllowed();
|
|
3188
|
+
const inspect = url.searchParams.get("inspect");
|
|
3057
3189
|
const kind = url.searchParams.get("kind");
|
|
3058
3190
|
const id = url.searchParams.get("id");
|
|
3059
3191
|
if (kind && !id || !kind && id) return json({ error: "kind and id must be paired" }, 400);
|
|
3060
3192
|
const target = targetFromQuery(url);
|
|
3061
3193
|
if ((kind || id) && !target) return json({ items: [] });
|
|
3194
|
+
if (inspect === "asset-content") {
|
|
3195
|
+
const allowed = /* @__PURE__ */ new Set(["inspect", "kind", "id"]);
|
|
3196
|
+
if ([...url.searchParams.keys()].some((key) => !allowed.has(key)) || target?.kind !== "brand:asset" || !target.resourceId) return json({ error: "exact brand asset kind and id required" }, 400);
|
|
3197
|
+
return handleBrandDiscussionAsset(ctx, req, {
|
|
3198
|
+
bookId: target.bookId,
|
|
3199
|
+
resourceId: target.resourceId
|
|
3200
|
+
});
|
|
3201
|
+
}
|
|
3202
|
+
if (inspect !== null && inspect !== "1") {
|
|
3203
|
+
return json({ error: "invalid inspection mode" }, 400);
|
|
3204
|
+
}
|
|
3062
3205
|
return json({
|
|
3063
3206
|
items: target ? await exact(ctx, req, target) : await search(ctx, req, url)
|
|
3064
3207
|
});
|
|
@@ -3099,7 +3242,8 @@ function createBrandRoutes(options) {
|
|
|
3099
3242
|
now: options.now ?? Date.now,
|
|
3100
3243
|
newId: options.newId ?? (() => crypto.randomUUID()),
|
|
3101
3244
|
maxUploadBytes: options.maxUploadBytes ?? 8 * 1024 * 1024,
|
|
3102
|
-
discussionBasePath: options.discussionBasePath ?? "/"
|
|
3245
|
+
discussionBasePath: options.discussionBasePath ?? "/",
|
|
3246
|
+
fetchPrivateAsset: options.fetchPrivateAsset ?? fetch
|
|
3103
3247
|
};
|
|
3104
3248
|
return async (req) => {
|
|
3105
3249
|
const url = new URL(req.url);
|