@odla-ai/brand 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +69 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -1
- package/dist/index.d.ts +28 -1
- package/dist/index.js +69 -32
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -627,6 +627,33 @@ declare function assertAssetContentType(value: unknown, kind?: string): string;
|
|
|
627
627
|
*/
|
|
628
628
|
declare function assertAnalysis(value: unknown): AssetAnalysis;
|
|
629
629
|
|
|
630
|
+
/**
|
|
631
|
+
* A stored row in the shape it was WRITTEN, ready to verify.
|
|
632
|
+
*
|
|
633
|
+
* The engine stores a `date` as the epoch ms it was given and hands a reader
|
|
634
|
+
* ISO-8601 text back. Brand digests rows that CONTAIN dates — a proposal's
|
|
635
|
+
* `reviewDigest` covers its `createdAt`, and an approval receipt's
|
|
636
|
+
* `receiptDigest` covers its own — so a row read straight out of the store can
|
|
637
|
+
* never match the digest stored beside it. Two production symptoms, both 409:
|
|
638
|
+
* resolving any proposal ("proposal changed since review") and reading a book's
|
|
639
|
+
* tokens after approval.
|
|
640
|
+
*
|
|
641
|
+
* Normalising at the READ is the fix, not tolerating both shapes in the
|
|
642
|
+
* verifier. Tolerance would repair a `safeTime` check and leave the digest
|
|
643
|
+
* failing, because the digest was taken over the number and nothing can change
|
|
644
|
+
* that after the fact.
|
|
645
|
+
*
|
|
646
|
+
* Anything that is not date-shaped text passes through untouched, so a row that
|
|
647
|
+
* never round-tripped verifies exactly as before. `json` attrs are left alone:
|
|
648
|
+
* their contents round-trip as written, which is why an `authorityConsumption`
|
|
649
|
+
* and the `createdAt` beside it disagreed at all.
|
|
650
|
+
*/
|
|
651
|
+
declare function rowAsWritten<T>(ns: string, row: T): T;
|
|
652
|
+
/** A stored approval receipt in the shape it was written. */
|
|
653
|
+
declare function receiptAsWritten<T>(row: T): T;
|
|
654
|
+
/** A stored proposal in the shape it was written, so `reviewDigest` matches. */
|
|
655
|
+
declare function proposalAsWritten<T>(row: T): T;
|
|
656
|
+
|
|
630
657
|
/** Stay materially below the server's whole-guards parser budget. */
|
|
631
658
|
declare function isBoundedBrandJson(root: unknown, limits?: {
|
|
632
659
|
maxDepth?: number;
|
|
@@ -1874,4 +1901,4 @@ interface CreateBrandIntegrationOptions {
|
|
|
1874
1901
|
*/
|
|
1875
1902
|
declare function createBrandIntegration(options?: CreateBrandIntegrationOptions): BrandIntegrationDescriptor;
|
|
1876
1903
|
|
|
1877
|
-
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, DESIGN_CONTENT_TYPES, type DeriveChartOptions, type DerivePaletteOptions, type DesignAssetGroup, type DesignBundle, type DesignBundleAsset, type DesignColorUse, type DesignDecompilation, type DesignDigest, type DesignManifestEntry, type DesignOutlineEntry, type DesignProp, type DesignTokenSets, type DesignTokenSkip, type Hsl, type IntegrationProvision, type IntegrationSecret, type IntegrationSetting, type LightnessDirection, MAX_COLORS, MAX_EXTERNALS, MAX_FONTS, MAX_HEADING_CHARS, MAX_OUTLINE_ENTRIES, MAX_PROPS, MAX_SWATCHES, MAX_THUMBNAIL_CHARS, 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, type ScannedDeclaration, SectionKind, SectionStatus, type SerializedAttr, type SerializedEntity, type SerializedLink, type SerializedLinkEnd, type SerializedSchema, Swatch, SwatchRole, type UpsertSectionInput, acceptProposalOps, adjustLightnessUntil, analogous, assertAnalysis, assertAssetContentType, assertHex, assertSectionContent, assertSwatches, assetTools, attachedBrandAssetIds, audienceFanoutOps, base64ByteLength, base64FromBytes, beginAssetDeleteOps, bookForChannel, bookTools, brandAuthorityRef, brandBotTrigger, brandDiscussionReferenceHref, brandDiscussionReferenceId, brandInputFor, brandIntegration, brandJsonDigest, brandRules, brandSkill, canonicalBrandJson, capString, capStringArray, clamp01, clampToGamut, collapseWhitespace, complementary, contrastRatio, contrastReport, createAssetOps, createBookOps, createBrandIntegration, createBrandPersona, createBrandRoutes, cssColorToHex, decodeEntities, deltaEOK, deltaEOKLab, deriveChartColors, derivePalette, digestDesignBundle, digestDesignHtml, dispatchBrandTurn, extractColors, extractDesignTokens, extractFonts, extractOutline, extractProps, extractThumbnailSvg, extractTitle, finishAssetDeleteOps, formatBrandDiscussionReference, groupAssets, hexToOklch, hslToRgb, htmlToText, inSrgbGamut, isBoundedBrandJson, isBrandHumanAuthorityConsumption, isDesignBundle, linearToSrgb, meetsAA, meetsAAA, monochrome, nearestNamedColor, normalizeHex, oklabToOklch, oklabToRgb, oklchToHex, oklchToOklab, paletteTools, parseBrandDiscussionReference, parseBrandDispatch, parseDesignBundle, parseHex, pickTextOn, proposalReviewSnapshot, proposePaletteOps, proposeSectionOps, readDesignManifest, readTools, recordAnalysisOps, rejectProposalOps, relativeLuminance, resolveDeps, resolveVarRefs, rgbToHsl, rgbToOklab, rotateHue, safeFileName, scanCustomProperties, sectionKey, splitComplementary, srgbToLinear, stripCssComments, styleSheetText, supportsBrandVision, swatchesFromDesignTokens, tetradic, tintShadeRamp, toHex, triadic, updateBookOps, upsertSectionOps, verifyBrandApprovalReceipt };
|
|
1904
|
+
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, DESIGN_CONTENT_TYPES, type DeriveChartOptions, type DerivePaletteOptions, type DesignAssetGroup, type DesignBundle, type DesignBundleAsset, type DesignColorUse, type DesignDecompilation, type DesignDigest, type DesignManifestEntry, type DesignOutlineEntry, type DesignProp, type DesignTokenSets, type DesignTokenSkip, type Hsl, type IntegrationProvision, type IntegrationSecret, type IntegrationSetting, type LightnessDirection, MAX_COLORS, MAX_EXTERNALS, MAX_FONTS, MAX_HEADING_CHARS, MAX_OUTLINE_ENTRIES, MAX_PROPS, MAX_SWATCHES, MAX_THUMBNAIL_CHARS, 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, type ScannedDeclaration, SectionKind, SectionStatus, type SerializedAttr, type SerializedEntity, type SerializedLink, type SerializedLinkEnd, type SerializedSchema, Swatch, SwatchRole, type UpsertSectionInput, acceptProposalOps, adjustLightnessUntil, analogous, assertAnalysis, assertAssetContentType, assertHex, assertSectionContent, assertSwatches, assetTools, attachedBrandAssetIds, audienceFanoutOps, base64ByteLength, base64FromBytes, beginAssetDeleteOps, bookForChannel, bookTools, brandAuthorityRef, brandBotTrigger, brandDiscussionReferenceHref, brandDiscussionReferenceId, brandInputFor, brandIntegration, brandJsonDigest, brandRules, brandSkill, canonicalBrandJson, capString, capStringArray, clamp01, clampToGamut, collapseWhitespace, complementary, contrastRatio, contrastReport, createAssetOps, createBookOps, createBrandIntegration, createBrandPersona, createBrandRoutes, cssColorToHex, decodeEntities, deltaEOK, deltaEOKLab, deriveChartColors, derivePalette, digestDesignBundle, digestDesignHtml, dispatchBrandTurn, extractColors, extractDesignTokens, extractFonts, extractOutline, extractProps, extractThumbnailSvg, extractTitle, finishAssetDeleteOps, formatBrandDiscussionReference, groupAssets, hexToOklch, hslToRgb, htmlToText, inSrgbGamut, isBoundedBrandJson, isBrandHumanAuthorityConsumption, isDesignBundle, linearToSrgb, meetsAA, meetsAAA, monochrome, nearestNamedColor, normalizeHex, oklabToOklch, oklabToRgb, oklchToHex, oklchToOklab, paletteTools, parseBrandDiscussionReference, parseBrandDispatch, parseDesignBundle, parseHex, pickTextOn, proposalAsWritten, proposalReviewSnapshot, proposePaletteOps, proposeSectionOps, readDesignManifest, readTools, receiptAsWritten, recordAnalysisOps, rejectProposalOps, relativeLuminance, resolveDeps, resolveVarRefs, rgbToHsl, rgbToOklab, rotateHue, rowAsWritten, safeFileName, scanCustomProperties, sectionKey, splitComplementary, srgbToLinear, stripCssComments, styleSheetText, supportsBrandVision, swatchesFromDesignTokens, tetradic, tintShadeRamp, toHex, triadic, updateBookOps, upsertSectionOps, verifyBrandApprovalReceipt };
|
package/dist/index.d.ts
CHANGED
|
@@ -627,6 +627,33 @@ declare function assertAssetContentType(value: unknown, kind?: string): string;
|
|
|
627
627
|
*/
|
|
628
628
|
declare function assertAnalysis(value: unknown): AssetAnalysis;
|
|
629
629
|
|
|
630
|
+
/**
|
|
631
|
+
* A stored row in the shape it was WRITTEN, ready to verify.
|
|
632
|
+
*
|
|
633
|
+
* The engine stores a `date` as the epoch ms it was given and hands a reader
|
|
634
|
+
* ISO-8601 text back. Brand digests rows that CONTAIN dates — a proposal's
|
|
635
|
+
* `reviewDigest` covers its `createdAt`, and an approval receipt's
|
|
636
|
+
* `receiptDigest` covers its own — so a row read straight out of the store can
|
|
637
|
+
* never match the digest stored beside it. Two production symptoms, both 409:
|
|
638
|
+
* resolving any proposal ("proposal changed since review") and reading a book's
|
|
639
|
+
* tokens after approval.
|
|
640
|
+
*
|
|
641
|
+
* Normalising at the READ is the fix, not tolerating both shapes in the
|
|
642
|
+
* verifier. Tolerance would repair a `safeTime` check and leave the digest
|
|
643
|
+
* failing, because the digest was taken over the number and nothing can change
|
|
644
|
+
* that after the fact.
|
|
645
|
+
*
|
|
646
|
+
* Anything that is not date-shaped text passes through untouched, so a row that
|
|
647
|
+
* never round-tripped verifies exactly as before. `json` attrs are left alone:
|
|
648
|
+
* their contents round-trip as written, which is why an `authorityConsumption`
|
|
649
|
+
* and the `createdAt` beside it disagreed at all.
|
|
650
|
+
*/
|
|
651
|
+
declare function rowAsWritten<T>(ns: string, row: T): T;
|
|
652
|
+
/** A stored approval receipt in the shape it was written. */
|
|
653
|
+
declare function receiptAsWritten<T>(row: T): T;
|
|
654
|
+
/** A stored proposal in the shape it was written, so `reviewDigest` matches. */
|
|
655
|
+
declare function proposalAsWritten<T>(row: T): T;
|
|
656
|
+
|
|
630
657
|
/** Stay materially below the server's whole-guards parser budget. */
|
|
631
658
|
declare function isBoundedBrandJson(root: unknown, limits?: {
|
|
632
659
|
maxDepth?: number;
|
|
@@ -1874,4 +1901,4 @@ interface CreateBrandIntegrationOptions {
|
|
|
1874
1901
|
*/
|
|
1875
1902
|
declare function createBrandIntegration(options?: CreateBrandIntegrationOptions): BrandIntegrationDescriptor;
|
|
1876
1903
|
|
|
1877
|
-
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, DESIGN_CONTENT_TYPES, type DeriveChartOptions, type DerivePaletteOptions, type DesignAssetGroup, type DesignBundle, type DesignBundleAsset, type DesignColorUse, type DesignDecompilation, type DesignDigest, type DesignManifestEntry, type DesignOutlineEntry, type DesignProp, type DesignTokenSets, type DesignTokenSkip, type Hsl, type IntegrationProvision, type IntegrationSecret, type IntegrationSetting, type LightnessDirection, MAX_COLORS, MAX_EXTERNALS, MAX_FONTS, MAX_HEADING_CHARS, MAX_OUTLINE_ENTRIES, MAX_PROPS, MAX_SWATCHES, MAX_THUMBNAIL_CHARS, 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, type ScannedDeclaration, SectionKind, SectionStatus, type SerializedAttr, type SerializedEntity, type SerializedLink, type SerializedLinkEnd, type SerializedSchema, Swatch, SwatchRole, type UpsertSectionInput, acceptProposalOps, adjustLightnessUntil, analogous, assertAnalysis, assertAssetContentType, assertHex, assertSectionContent, assertSwatches, assetTools, attachedBrandAssetIds, audienceFanoutOps, base64ByteLength, base64FromBytes, beginAssetDeleteOps, bookForChannel, bookTools, brandAuthorityRef, brandBotTrigger, brandDiscussionReferenceHref, brandDiscussionReferenceId, brandInputFor, brandIntegration, brandJsonDigest, brandRules, brandSkill, canonicalBrandJson, capString, capStringArray, clamp01, clampToGamut, collapseWhitespace, complementary, contrastRatio, contrastReport, createAssetOps, createBookOps, createBrandIntegration, createBrandPersona, createBrandRoutes, cssColorToHex, decodeEntities, deltaEOK, deltaEOKLab, deriveChartColors, derivePalette, digestDesignBundle, digestDesignHtml, dispatchBrandTurn, extractColors, extractDesignTokens, extractFonts, extractOutline, extractProps, extractThumbnailSvg, extractTitle, finishAssetDeleteOps, formatBrandDiscussionReference, groupAssets, hexToOklch, hslToRgb, htmlToText, inSrgbGamut, isBoundedBrandJson, isBrandHumanAuthorityConsumption, isDesignBundle, linearToSrgb, meetsAA, meetsAAA, monochrome, nearestNamedColor, normalizeHex, oklabToOklch, oklabToRgb, oklchToHex, oklchToOklab, paletteTools, parseBrandDiscussionReference, parseBrandDispatch, parseDesignBundle, parseHex, pickTextOn, proposalReviewSnapshot, proposePaletteOps, proposeSectionOps, readDesignManifest, readTools, recordAnalysisOps, rejectProposalOps, relativeLuminance, resolveDeps, resolveVarRefs, rgbToHsl, rgbToOklab, rotateHue, safeFileName, scanCustomProperties, sectionKey, splitComplementary, srgbToLinear, stripCssComments, styleSheetText, supportsBrandVision, swatchesFromDesignTokens, tetradic, tintShadeRamp, toHex, triadic, updateBookOps, upsertSectionOps, verifyBrandApprovalReceipt };
|
|
1904
|
+
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, DESIGN_CONTENT_TYPES, type DeriveChartOptions, type DerivePaletteOptions, type DesignAssetGroup, type DesignBundle, type DesignBundleAsset, type DesignColorUse, type DesignDecompilation, type DesignDigest, type DesignManifestEntry, type DesignOutlineEntry, type DesignProp, type DesignTokenSets, type DesignTokenSkip, type Hsl, type IntegrationProvision, type IntegrationSecret, type IntegrationSetting, type LightnessDirection, MAX_COLORS, MAX_EXTERNALS, MAX_FONTS, MAX_HEADING_CHARS, MAX_OUTLINE_ENTRIES, MAX_PROPS, MAX_SWATCHES, MAX_THUMBNAIL_CHARS, 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, type ScannedDeclaration, SectionKind, SectionStatus, type SerializedAttr, type SerializedEntity, type SerializedLink, type SerializedLinkEnd, type SerializedSchema, Swatch, SwatchRole, type UpsertSectionInput, acceptProposalOps, adjustLightnessUntil, analogous, assertAnalysis, assertAssetContentType, assertHex, assertSectionContent, assertSwatches, assetTools, attachedBrandAssetIds, audienceFanoutOps, base64ByteLength, base64FromBytes, beginAssetDeleteOps, bookForChannel, bookTools, brandAuthorityRef, brandBotTrigger, brandDiscussionReferenceHref, brandDiscussionReferenceId, brandInputFor, brandIntegration, brandJsonDigest, brandRules, brandSkill, canonicalBrandJson, capString, capStringArray, clamp01, clampToGamut, collapseWhitespace, complementary, contrastRatio, contrastReport, createAssetOps, createBookOps, createBrandIntegration, createBrandPersona, createBrandRoutes, cssColorToHex, decodeEntities, deltaEOK, deltaEOKLab, deriveChartColors, derivePalette, digestDesignBundle, digestDesignHtml, dispatchBrandTurn, extractColors, extractDesignTokens, extractFonts, extractOutline, extractProps, extractThumbnailSvg, extractTitle, finishAssetDeleteOps, formatBrandDiscussionReference, groupAssets, hexToOklch, hslToRgb, htmlToText, inSrgbGamut, isBoundedBrandJson, isBrandHumanAuthorityConsumption, isDesignBundle, linearToSrgb, meetsAA, meetsAAA, monochrome, nearestNamedColor, normalizeHex, oklabToOklch, oklabToRgb, oklchToHex, oklchToOklab, paletteTools, parseBrandDiscussionReference, parseBrandDispatch, parseDesignBundle, parseHex, pickTextOn, proposalAsWritten, proposalReviewSnapshot, proposePaletteOps, proposeSectionOps, readDesignManifest, readTools, receiptAsWritten, recordAnalysisOps, rejectProposalOps, relativeLuminance, resolveDeps, resolveVarRefs, rgbToHsl, rgbToOklab, rotateHue, rowAsWritten, safeFileName, scanCustomProperties, sectionKey, splitComplementary, srgbToLinear, stripCssComments, styleSheetText, supportsBrandVision, swatchesFromDesignTokens, tetradic, tintShadeRamp, toHex, triadic, updateBookOps, upsertSectionOps, verifyBrandApprovalReceipt };
|
package/dist/index.js
CHANGED
|
@@ -558,8 +558,40 @@ function assertAnalysis(value) {
|
|
|
558
558
|
};
|
|
559
559
|
}
|
|
560
560
|
|
|
561
|
+
// src/read-shape.ts
|
|
562
|
+
var record = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
563
|
+
var DATE_FIELDS = /* @__PURE__ */ new Map();
|
|
564
|
+
for (const [ns, entity] of Object.entries(BRAND_SCHEMA.entities))
|
|
565
|
+
DATE_FIELDS.set(
|
|
566
|
+
ns,
|
|
567
|
+
new Set(
|
|
568
|
+
Object.entries(entity.attrs).filter(([, attr]) => attr.type === "date").map(([label]) => label)
|
|
569
|
+
)
|
|
570
|
+
);
|
|
571
|
+
function rowAsWritten(ns, row) {
|
|
572
|
+
const dates = DATE_FIELDS.get(ns);
|
|
573
|
+
if (!dates?.size || !record(row)) return row;
|
|
574
|
+
let changed = false;
|
|
575
|
+
const out = { ...row };
|
|
576
|
+
for (const field of dates) {
|
|
577
|
+
const value = out[field];
|
|
578
|
+
if (typeof value !== "string") continue;
|
|
579
|
+
const parsed = Date.parse(value);
|
|
580
|
+
if (!Number.isSafeInteger(parsed) || parsed < 0) continue;
|
|
581
|
+
out[field] = parsed;
|
|
582
|
+
changed = true;
|
|
583
|
+
}
|
|
584
|
+
return changed ? out : row;
|
|
585
|
+
}
|
|
586
|
+
function receiptAsWritten(row) {
|
|
587
|
+
return rowAsWritten(BRAND_NS.approvalReceipt, row);
|
|
588
|
+
}
|
|
589
|
+
function proposalAsWritten(row) {
|
|
590
|
+
return rowAsWritten(BRAND_NS.proposal, row);
|
|
591
|
+
}
|
|
592
|
+
|
|
561
593
|
// src/review-json.ts
|
|
562
|
-
var
|
|
594
|
+
var record2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
563
595
|
function isBoundedBrandJson(root, limits = {}) {
|
|
564
596
|
const maxDepth = limits.maxDepth ?? 12;
|
|
565
597
|
const maxNodes = limits.maxNodes ?? 2048;
|
|
@@ -583,7 +615,7 @@ function isBoundedBrandJson(root, limits = {}) {
|
|
|
583
615
|
if (Array.isArray(value)) {
|
|
584
616
|
for (const child of value)
|
|
585
617
|
stack.push({ value: child, depth: depth + 1 });
|
|
586
|
-
} else if (
|
|
618
|
+
} else if (record2(value)) {
|
|
587
619
|
for (const child of Object.values(value))
|
|
588
620
|
stack.push({ value: child, depth: depth + 1 });
|
|
589
621
|
} else {
|
|
@@ -620,7 +652,7 @@ async function brandJsonDigest(value) {
|
|
|
620
652
|
|
|
621
653
|
// src/review.ts
|
|
622
654
|
var DIGEST = /^sha256:[0-9a-f]{64}$/;
|
|
623
|
-
var
|
|
655
|
+
var record3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
624
656
|
var exactKeys = (value, required, optional = []) => {
|
|
625
657
|
const allowed = /* @__PURE__ */ new Set([...required, ...optional]);
|
|
626
658
|
return required.every((key) => Object.hasOwn(value, key)) && Object.keys(value).every((key) => allowed.has(key));
|
|
@@ -645,15 +677,15 @@ var SNAPSHOT_REQUIRED = [
|
|
|
645
677
|
"createdAt"
|
|
646
678
|
];
|
|
647
679
|
function validSnapshotShape(value) {
|
|
648
|
-
if (!
|
|
680
|
+
if (!record3(value) || !exactKeys(value, SNAPSHOT_REQUIRED)) return false;
|
|
649
681
|
const provenance = value.provenance;
|
|
650
|
-
return boundedString(value.id) && boundedString(value.bookId) && typeof value.kind === "string" && PROPOSAL_KINDS.includes(value.kind) && value.status === "open" &&
|
|
682
|
+
return boundedString(value.id) && boundedString(value.bookId) && typeof value.kind === "string" && PROPOSAL_KINDS.includes(value.kind) && value.status === "open" && record3(value.payload) && boundedString(value.rationale, 2e3) && record3(provenance) && exactKeys(provenance, [
|
|
651
683
|
"sourceAssetId",
|
|
652
684
|
"sourceAsset",
|
|
653
685
|
"messageId",
|
|
654
686
|
"turnId",
|
|
655
687
|
"taintLabels"
|
|
656
|
-
]) && (provenance.sourceAssetId === null || boundedString(provenance.sourceAssetId)) && (provenance.sourceAsset === null ||
|
|
688
|
+
]) && (provenance.sourceAssetId === null || boundedString(provenance.sourceAssetId)) && (provenance.sourceAsset === null || record3(provenance.sourceAsset) && exactKeys(provenance.sourceAsset, [
|
|
657
689
|
"assetId",
|
|
658
690
|
"contentDigest",
|
|
659
691
|
"objectEtag",
|
|
@@ -686,8 +718,8 @@ var CONSUMPTION_REQUIRED = [
|
|
|
686
718
|
"consumedAt"
|
|
687
719
|
];
|
|
688
720
|
function isBrandHumanAuthorityConsumption(value) {
|
|
689
|
-
if (!
|
|
690
|
-
return boundedString(value.id) && boundedString(value.grantId) && Number.isSafeInteger(value.grantVersion) && value.grantVersion > 0 && Number.isSafeInteger(value.useNumber) && value.useNumber > 0 && boundedString(value.actorPrincipalId) && value.actorKind === "human" && boundedString(value.credentialId) && value.credentialKind === "clerk" && boundedString(value.appId) && typeof value.appIncarnation === "string" && /^[a-f0-9]{32}$/.test(value.appIncarnation) && value.capability === "brand.proposal.resolve" && value.projectCapability === "brand.approve" && value.effect === "internal" && typeof value.actionDigest === "string" && DIGEST.test(value.actionDigest) && typeof value.resourceDigest === "string" && DIGEST.test(value.resourceDigest) &&
|
|
721
|
+
if (!record3(value) || !exactKeys(value, CONSUMPTION_REQUIRED)) return false;
|
|
722
|
+
return boundedString(value.id) && boundedString(value.grantId) && Number.isSafeInteger(value.grantVersion) && value.grantVersion > 0 && Number.isSafeInteger(value.useNumber) && value.useNumber > 0 && boundedString(value.actorPrincipalId) && value.actorKind === "human" && boundedString(value.credentialId) && value.credentialKind === "clerk" && boundedString(value.appId) && typeof value.appIncarnation === "string" && /^[a-f0-9]{32}$/.test(value.appIncarnation) && value.capability === "brand.proposal.resolve" && value.projectCapability === "brand.approve" && value.effect === "internal" && typeof value.actionDigest === "string" && DIGEST.test(value.actionDigest) && typeof value.resourceDigest === "string" && DIGEST.test(value.resourceDigest) && record3(value.constraintEvidence) && boundedString(value.consumptionIdempotencyKey) && typeof value.requestDigest === "string" && DIGEST.test(value.requestDigest) && safeTime(value.consumedAt);
|
|
691
723
|
}
|
|
692
724
|
var RECEIPT_REQUIRED = [
|
|
693
725
|
"version",
|
|
@@ -713,10 +745,10 @@ async function verifyBrandApprovalReceipt(receipt2) {
|
|
|
713
745
|
try {
|
|
714
746
|
if (!isBoundedBrandJson(receipt2, { maxDepth: 14, maxNodes: 2500, maxBytes: 48 * 1024 }))
|
|
715
747
|
return false;
|
|
716
|
-
if (!
|
|
748
|
+
if (!record3(receipt2) || !exactKeys(receipt2, RECEIPT_REQUIRED, ["paletteId", "resolutionNote"]))
|
|
717
749
|
return false;
|
|
718
750
|
const binding = receipt2.decisionBinding;
|
|
719
|
-
if (receipt2.version !== 1 || !boundedString(receipt2.id) || !boundedString(receipt2.mutationKey) || !boundedString(receipt2.bookId) || !boundedString(receipt2.proposalId) || receipt2.resolution !== "accepted" && receipt2.resolution !== "rejected" || !validSnapshotShape(receipt2.reviewedProposal) || typeof receipt2.actionDigest !== "string" || !DIGEST.test(receipt2.actionDigest) || !
|
|
751
|
+
if (receipt2.version !== 1 || !boundedString(receipt2.id) || !boundedString(receipt2.mutationKey) || !boundedString(receipt2.bookId) || !boundedString(receipt2.proposalId) || receipt2.resolution !== "accepted" && receipt2.resolution !== "rejected" || !validSnapshotShape(receipt2.reviewedProposal) || typeof receipt2.actionDigest !== "string" || !DIGEST.test(receipt2.actionDigest) || !record3(binding) || !exactKeys(binding, [
|
|
720
752
|
"version",
|
|
721
753
|
"bookVersion",
|
|
722
754
|
"activationRevision",
|
|
@@ -2481,7 +2513,7 @@ async function linkedAsset(ctx, book, assetId, allowDeleting = false) {
|
|
|
2481
2513
|
book: {}
|
|
2482
2514
|
}
|
|
2483
2515
|
});
|
|
2484
|
-
const row = (result[BRAND_NS.asset] ?? [])[0];
|
|
2516
|
+
const row = rowAsWritten(BRAND_NS.asset, (result[BRAND_NS.asset] ?? [])[0]);
|
|
2485
2517
|
const links = row?.book;
|
|
2486
2518
|
if (!row || row.bookId !== book.id || !Array.isArray(links) || links.length !== 1 || links[0]?.id !== book.id || row.status !== "live" && !(allowDeleting && row.status === "deleting")) throw new BrandNotFoundError(`asset ${assetId}`);
|
|
2487
2519
|
return row;
|
|
@@ -2555,7 +2587,7 @@ async function loadBook(db, bookId) {
|
|
|
2555
2587
|
const res = await db.query({ [BRAND_NS.book]: { $: { where: { id: bookId } } } });
|
|
2556
2588
|
const row = (res[BRAND_NS.book] ?? [])[0];
|
|
2557
2589
|
if (!row) throw new BrandNotFoundError(`brand book ${bookId}`);
|
|
2558
|
-
return row;
|
|
2590
|
+
return rowAsWritten(BRAND_NS.book, row);
|
|
2559
2591
|
}
|
|
2560
2592
|
async function loadMemberBook(db, bookId, actorId) {
|
|
2561
2593
|
const book = await loadBook(db, bookId);
|
|
@@ -2610,14 +2642,14 @@ async function uploadAsset(ctx, req, bookId) {
|
|
|
2610
2642
|
"internal",
|
|
2611
2643
|
book.id
|
|
2612
2644
|
);
|
|
2613
|
-
const
|
|
2645
|
+
const record7 = await ctx.db.storage.upload(
|
|
2614
2646
|
path,
|
|
2615
2647
|
file,
|
|
2616
2648
|
contentType,
|
|
2617
2649
|
{ private: true }
|
|
2618
2650
|
);
|
|
2619
|
-
if (
|
|
2620
|
-
await ctx.db.storage.delete(
|
|
2651
|
+
if (record7.path !== path) {
|
|
2652
|
+
await ctx.db.storage.delete(record7.path);
|
|
2621
2653
|
throw new BrandConflictError(
|
|
2622
2654
|
"private storage returned an unexpected asset path"
|
|
2623
2655
|
);
|
|
@@ -2636,11 +2668,11 @@ async function uploadAsset(ctx, req, bookId) {
|
|
|
2636
2668
|
id,
|
|
2637
2669
|
bookId: book.id,
|
|
2638
2670
|
kind,
|
|
2639
|
-
path:
|
|
2640
|
-
storageObjectId:
|
|
2671
|
+
path: record7.path,
|
|
2672
|
+
storageObjectId: record7.id,
|
|
2641
2673
|
contentDigest: await contentDigest(file),
|
|
2642
2674
|
contentType,
|
|
2643
|
-
size:
|
|
2675
|
+
size: record7.size,
|
|
2644
2676
|
uploadedBy: ctx.actor.id,
|
|
2645
2677
|
uploadedAuthorityRef: authority.authorityRef,
|
|
2646
2678
|
audience: book.memberIds,
|
|
@@ -2667,7 +2699,7 @@ async function uploadAsset(ctx, req, bookId) {
|
|
|
2667
2699
|
asPrincipalKind: "human"
|
|
2668
2700
|
});
|
|
2669
2701
|
} catch (error) {
|
|
2670
|
-
await ctx.db.storage.delete(
|
|
2702
|
+
await ctx.db.storage.delete(record7.path);
|
|
2671
2703
|
throw error;
|
|
2672
2704
|
}
|
|
2673
2705
|
return json(await linkedAsset(ctx, book, id), 201);
|
|
@@ -2782,7 +2814,7 @@ async function handleAssetItem(ctx, req, bookId, assetId) {
|
|
|
2782
2814
|
async function handleBooksRoot(ctx, req) {
|
|
2783
2815
|
if (req.method === "GET") {
|
|
2784
2816
|
const res = await ctx.db.query({ [BRAND_NS.book]: { $: { order: { createdAt: "asc" } } } });
|
|
2785
|
-
const books = (res[BRAND_NS.book] ?? []).filter(
|
|
2817
|
+
const books = (res[BRAND_NS.book] ?? []).map((b) => rowAsWritten(BRAND_NS.book, b)).filter(
|
|
2786
2818
|
(b) => isMember(b, ctx.actor.id)
|
|
2787
2819
|
);
|
|
2788
2820
|
return json({ books });
|
|
@@ -2947,7 +2979,7 @@ var SNAPSHOT_KEYS = [
|
|
|
2947
2979
|
"reviewDigest",
|
|
2948
2980
|
"status"
|
|
2949
2981
|
];
|
|
2950
|
-
var
|
|
2982
|
+
var record4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2951
2983
|
function parseProposalResolutionRequest(body, bookId, proposalId) {
|
|
2952
2984
|
const allowed = /* @__PURE__ */ new Set([
|
|
2953
2985
|
"mutationId",
|
|
@@ -2991,13 +3023,13 @@ function proposalReviewSnapshot(proposal) {
|
|
|
2991
3023
|
function parseReviewedProposal(value, bookId, proposalId) {
|
|
2992
3024
|
if (!isBoundedBrandJson(value, { maxDepth: 12, maxNodes: 1500, maxBytes: 32 * 1024 }))
|
|
2993
3025
|
throw new BrandInputError('"reviewedProposal" is too deeply nested, complex, or large');
|
|
2994
|
-
if (!
|
|
3026
|
+
if (!record4(value)) throw new BrandInputError('"reviewedProposal" must be an object');
|
|
2995
3027
|
const keys = Object.keys(value).sort();
|
|
2996
3028
|
if (keys.length !== SNAPSHOT_KEYS.length || !SNAPSHOT_KEYS.every((key, index) => key === keys[index])) throw new BrandInputError('"reviewedProposal" has an invalid shape');
|
|
2997
3029
|
if (value.id !== proposalId || value.bookId !== bookId || value.status !== "open")
|
|
2998
3030
|
throw new BrandInputError('"reviewedProposal" must identify this open proposal');
|
|
2999
|
-
if (typeof value.kind !== "string" || !PROPOSAL_KINDS.includes(value.kind) || !
|
|
3000
|
-
if (!
|
|
3031
|
+
if (typeof value.kind !== "string" || !PROPOSAL_KINDS.includes(value.kind) || !record4(value.payload) || typeof value.rationale !== "string" || !Array.isArray(value.audience) || value.audience.length < 1 || value.audience.length > 100 || value.audience.some((id) => typeof id !== "string" || id.length < 1 || id.length > 200) || new Set(value.audience).size !== value.audience.length || typeof value.createdBy !== "string" || value.createdBy.length < 1 || value.createdBy.length > 200 || typeof value.createdAuthorityRef !== "string" || value.createdAuthorityRef.length < 1 || value.createdAuthorityRef.length > 200 || !Number.isSafeInteger(value.createdAt) || value.createdAt < 0 || typeof value.reviewDigest !== "string" || !/^sha256:[0-9a-f]{64}$/.test(value.reviewDigest)) throw new BrandInputError('"reviewedProposal" has invalid fields');
|
|
3032
|
+
if (!record4(value.provenance) || Object.keys(value.provenance).sort().join(",") !== "messageId,sourceAsset,sourceAssetId,taintLabels,turnId" || value.provenance.sourceAssetId !== null && (typeof value.provenance.sourceAssetId !== "string" || value.provenance.sourceAssetId.length < 1 || value.provenance.sourceAssetId.length > 200) || value.provenance.sourceAsset !== null && (!record4(value.provenance.sourceAsset) || Object.keys(value.provenance.sourceAsset).sort().join(",") !== "analysisDigest,analysisRevision,assetId,contentDigest,contentType,objectEtag,objectSize,pathDigest" || typeof value.provenance.sourceAsset.assetId !== "string" || value.provenance.sourceAsset.assetId.length < 1 || value.provenance.sourceAsset.assetId.length > 200 || typeof value.provenance.sourceAsset.objectEtag !== "string" || value.provenance.sourceAsset.objectEtag.length < 1 || value.provenance.sourceAsset.objectEtag.length > 200 || !Number.isSafeInteger(value.provenance.sourceAsset.objectSize) || value.provenance.sourceAsset.objectSize < 1 || typeof value.provenance.sourceAsset.pathDigest !== "string" || !/^sha256:[0-9a-f]{64}$/.test(value.provenance.sourceAsset.pathDigest) || value.provenance.sourceAsset.contentType !== null && (typeof value.provenance.sourceAsset.contentType !== "string" || value.provenance.sourceAsset.contentType.length < 1 || value.provenance.sourceAsset.contentType.length > 160) || typeof value.provenance.sourceAsset.contentDigest !== "string" || !/^sha256:[0-9a-f]{64}$/.test(value.provenance.sourceAsset.contentDigest) || value.provenance.sourceAsset.analysisRevision !== null && (!Number.isSafeInteger(value.provenance.sourceAsset.analysisRevision) || value.provenance.sourceAsset.analysisRevision < 0) || value.provenance.sourceAsset.analysisDigest !== null && (typeof value.provenance.sourceAsset.analysisDigest !== "string" || !/^sha256:[0-9a-f]{64}$/.test(
|
|
3001
3033
|
value.provenance.sourceAsset.analysisDigest
|
|
3002
3034
|
)) || value.provenance.sourceAsset.assetId !== value.provenance.sourceAssetId) || value.provenance.sourceAssetId === null !== (value.provenance.sourceAsset === null) || value.provenance.messageId !== null && (typeof value.provenance.messageId !== "string" || value.provenance.messageId.length < 1 || value.provenance.messageId.length > 200) || value.provenance.turnId !== null && (typeof value.provenance.turnId !== "string" || value.provenance.turnId.length < 1 || value.provenance.turnId.length > 200) || !Array.isArray(value.provenance.taintLabels) || value.provenance.taintLabels.length > 16 || value.provenance.taintLabels.some((label) => typeof label !== "string" || label.length < 1 || label.length > 120) || new Set(value.provenance.taintLabels).size !== value.provenance.taintLabels.length) throw new BrandInputError('"reviewedProposal.provenance" is invalid');
|
|
3003
3035
|
return value;
|
|
@@ -3170,7 +3202,7 @@ async function proposalReceiptByMutation(ctx, mutationKey) {
|
|
|
3170
3202
|
const row = (result[BRAND_NS.approvalReceipt] ?? [])[0];
|
|
3171
3203
|
if (!row || !Array.isArray(row.book) || row.book.length !== 1 || row.book[0]?.id !== row.bookId) return void 0;
|
|
3172
3204
|
const { book: _book, ...receipt2 } = row;
|
|
3173
|
-
return receipt2;
|
|
3205
|
+
return receiptAsWritten(receipt2);
|
|
3174
3206
|
}
|
|
3175
3207
|
async function consumeProposalAuthority(ctx, req, bookId, proposalId, actionDigest, mutationKey) {
|
|
3176
3208
|
const authority = await ctx.consumeHumanExact({
|
|
@@ -3204,7 +3236,8 @@ async function receipt(ctx, id, actionDigest, expected) {
|
|
|
3204
3236
|
});
|
|
3205
3237
|
const row = (result[BRAND_NS.approvalReceipt] ?? [])[0];
|
|
3206
3238
|
if (!row || row.actionDigest !== actionDigest || row.resolution !== "accepted" || row.bookId !== expected.bookId || row.reviewedProposal.bookId !== expected.bookId || row.reviewedProposal.kind !== expected.kind || !Array.isArray(row.book) || row.book.length !== 1 || row.book[0]?.id !== expected.bookId || expected.paletteId !== void 0 && row.paletteId !== expected.paletteId || expected.proposalId !== void 0 && row.proposalId !== expected.proposalId || expected.content !== void 0 && canonicalBrandJson(row.reviewedProposal.payload.content) !== canonicalBrandJson(expected.content)) throw new BrandConflictError(`approval receipt ${id} is invalid`);
|
|
3207
|
-
const { book: _book, ...
|
|
3239
|
+
const { book: _book, ...stored } = row;
|
|
3240
|
+
const unhydrated = receiptAsWritten(stored);
|
|
3208
3241
|
if (!await verifyBrandApprovalReceipt(unhydrated))
|
|
3209
3242
|
throw new BrandConflictError(`approval receipt ${id} is invalid`);
|
|
3210
3243
|
return unhydrated;
|
|
@@ -3442,9 +3475,9 @@ async function proposalDecisionState(ctx, req, book, proposal, resolution, recei
|
|
|
3442
3475
|
}
|
|
3443
3476
|
|
|
3444
3477
|
// src/routes/proposals.ts
|
|
3445
|
-
var
|
|
3478
|
+
var record5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3446
3479
|
var sameStrings2 = (left, right) => left.length === right.length && left.every((value, index) => value === right[index]);
|
|
3447
|
-
var guardFailure2 = (error) =>
|
|
3480
|
+
var guardFailure2 = (error) => record5(error) && error.code === "transact_guard_failed";
|
|
3448
3481
|
async function handleProposalResolution(ctx, req, bookId, proposalId) {
|
|
3449
3482
|
if (req.method !== "POST") return methodNotAllowed();
|
|
3450
3483
|
const book = await loadMemberBook(ctx.db, bookId, ctx.actor.id);
|
|
@@ -3491,7 +3524,7 @@ async function handleProposalResolution(ctx, req, bookId, proposalId) {
|
|
|
3491
3524
|
book: {}
|
|
3492
3525
|
}
|
|
3493
3526
|
});
|
|
3494
|
-
const proposal = (result[BRAND_NS.proposal] ?? [])[0];
|
|
3527
|
+
const proposal = proposalAsWritten((result[BRAND_NS.proposal] ?? [])[0]);
|
|
3495
3528
|
if (!proposal || proposal.bookId !== book.id || !Array.isArray(proposal.book) || proposal.book.length !== 1 || proposal.book[0]?.id !== book.id) throw new BrandNotFoundError(`proposal ${proposalId}`);
|
|
3496
3529
|
const current = proposalReviewSnapshot(proposal);
|
|
3497
3530
|
const { reviewDigest, ...unsignedReview } = current;
|
|
@@ -3624,7 +3657,7 @@ async function handleProposalResolution(ctx, req, bookId, proposalId) {
|
|
|
3624
3657
|
}
|
|
3625
3658
|
|
|
3626
3659
|
// src/routes/tokens.ts
|
|
3627
|
-
var
|
|
3660
|
+
var record6 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3628
3661
|
var missing = (bookId) => {
|
|
3629
3662
|
throw new BrandNotFoundError(`compiled tokens for brand book ${bookId}`);
|
|
3630
3663
|
};
|
|
@@ -3637,13 +3670,14 @@ async function acceptedReceipt(db, bookId, receiptId, actionDigest) {
|
|
|
3637
3670
|
});
|
|
3638
3671
|
const receipt2 = (result[BRAND_NS.approvalReceipt] ?? [])[0];
|
|
3639
3672
|
if (!receipt2 || receipt2.resolution !== "accepted" || receipt2.actionDigest !== actionDigest || !Array.isArray(receipt2.book) || receipt2.book.length !== 1 || receipt2.book[0]?.id !== bookId) return missing(bookId);
|
|
3640
|
-
const { book: _book, ...
|
|
3673
|
+
const { book: _book, ...stored } = receipt2;
|
|
3674
|
+
const unhydrated = receiptAsWritten(stored);
|
|
3641
3675
|
if (!await verifyBrandApprovalReceipt(unhydrated)) return missing(bookId);
|
|
3642
3676
|
return unhydrated;
|
|
3643
3677
|
}
|
|
3644
3678
|
async function approvedCache(db, book) {
|
|
3645
3679
|
const cache = book.tokens;
|
|
3646
|
-
if (!cache || !
|
|
3680
|
+
if (!cache || !record6(cache.light) || !record6(cache.dark) || !book.activePaletteId || cache.paletteId !== book.activePaletteId || !cache.paletteReceiptId || !cache.paletteActionDigest || !cache.sourceDigest) return missing(book.id);
|
|
3647
3681
|
const paletteResult = await db.query({
|
|
3648
3682
|
[BRAND_NS.palette]: {
|
|
3649
3683
|
$: { where: { id: cache.paletteId, bookId: book.id } },
|
|
@@ -4427,11 +4461,13 @@ export {
|
|
|
4427
4461
|
parseDesignBundle,
|
|
4428
4462
|
parseHex,
|
|
4429
4463
|
pickTextOn,
|
|
4464
|
+
proposalAsWritten,
|
|
4430
4465
|
proposalReviewSnapshot,
|
|
4431
4466
|
proposePaletteOps,
|
|
4432
4467
|
proposeSectionOps,
|
|
4433
4468
|
readDesignManifest,
|
|
4434
4469
|
readTools,
|
|
4470
|
+
receiptAsWritten,
|
|
4435
4471
|
recordAnalysisOps,
|
|
4436
4472
|
rejectProposalOps,
|
|
4437
4473
|
relativeLuminance,
|
|
@@ -4441,6 +4477,7 @@ export {
|
|
|
4441
4477
|
rgbToHsl,
|
|
4442
4478
|
rgbToOklab,
|
|
4443
4479
|
rotateHue,
|
|
4480
|
+
rowAsWritten,
|
|
4444
4481
|
safeFileName,
|
|
4445
4482
|
scanCustomProperties,
|
|
4446
4483
|
sectionKey,
|