@odla-ai/brand 0.5.0 → 0.7.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 +101 -50
- 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 +101 -50
- 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
|
@@ -154,24 +154,6 @@ var BrandReviewStateChangedError = class extends BrandConflictError {
|
|
|
154
154
|
}
|
|
155
155
|
};
|
|
156
156
|
|
|
157
|
-
// src/deps.ts
|
|
158
|
-
async function defaultFetchBytes(url) {
|
|
159
|
-
const res = await fetch(url);
|
|
160
|
-
if (!res.ok) throw new Error(`asset fetch failed: ${res.status} for ${url}`);
|
|
161
|
-
return {
|
|
162
|
-
bytes: new Uint8Array(await res.arrayBuffer()),
|
|
163
|
-
contentType: res.headers.get("content-type") ?? "application/octet-stream"
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
function resolveDeps(deps) {
|
|
167
|
-
return {
|
|
168
|
-
db: deps.db,
|
|
169
|
-
now: deps.now ?? Date.now,
|
|
170
|
-
newId: deps.newId ?? (() => crypto.randomUUID()),
|
|
171
|
-
fetchBytes: deps.fetchBytes ?? defaultFetchBytes
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
|
|
175
157
|
// src/schema.ts
|
|
176
158
|
var a = (type, o = {}) => ({
|
|
177
159
|
type,
|
|
@@ -358,6 +340,70 @@ var BRAND_SCHEMA = {
|
|
|
358
340
|
}
|
|
359
341
|
};
|
|
360
342
|
|
|
343
|
+
// src/read-shape.ts
|
|
344
|
+
var record = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
345
|
+
var DATE_FIELDS = /* @__PURE__ */ new Map();
|
|
346
|
+
for (const [ns, entity] of Object.entries(BRAND_SCHEMA.entities))
|
|
347
|
+
DATE_FIELDS.set(
|
|
348
|
+
ns,
|
|
349
|
+
new Set(
|
|
350
|
+
Object.entries(entity.attrs).filter(([, attr]) => attr.type === "date").map(([label]) => label)
|
|
351
|
+
)
|
|
352
|
+
);
|
|
353
|
+
function rowAsWritten(ns, row) {
|
|
354
|
+
const dates = DATE_FIELDS.get(ns);
|
|
355
|
+
if (!dates?.size || !record(row)) return row;
|
|
356
|
+
let changed = false;
|
|
357
|
+
const out = { ...row };
|
|
358
|
+
for (const field of dates) {
|
|
359
|
+
const value = out[field];
|
|
360
|
+
if (typeof value !== "string") continue;
|
|
361
|
+
const parsed = Date.parse(value);
|
|
362
|
+
if (!Number.isSafeInteger(parsed) || parsed < 0) continue;
|
|
363
|
+
out[field] = parsed;
|
|
364
|
+
changed = true;
|
|
365
|
+
}
|
|
366
|
+
return changed ? out : row;
|
|
367
|
+
}
|
|
368
|
+
function receiptAsWritten(row) {
|
|
369
|
+
return rowAsWritten(BRAND_NS.approvalReceipt, row);
|
|
370
|
+
}
|
|
371
|
+
function proposalAsWritten(row) {
|
|
372
|
+
return rowAsWritten(BRAND_NS.proposal, row);
|
|
373
|
+
}
|
|
374
|
+
function resultAsWritten(result) {
|
|
375
|
+
const out = { ...result };
|
|
376
|
+
for (const [ns, rows] of Object.entries(out)) {
|
|
377
|
+
if (Array.isArray(rows)) out[ns] = rows.map((row) => rowAsWritten(ns, row));
|
|
378
|
+
}
|
|
379
|
+
return out;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// src/deps.ts
|
|
383
|
+
async function defaultFetchBytes(url) {
|
|
384
|
+
const res = await fetch(url);
|
|
385
|
+
if (!res.ok) throw new Error(`asset fetch failed: ${res.status} for ${url}`);
|
|
386
|
+
return {
|
|
387
|
+
bytes: new Uint8Array(await res.arrayBuffer()),
|
|
388
|
+
contentType: res.headers.get("content-type") ?? "application/octet-stream"
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
function readingAsWritten(db) {
|
|
392
|
+
return {
|
|
393
|
+
query: async (q) => resultAsWritten(await db.query(q)),
|
|
394
|
+
transact: (ops, opts) => db.transact(ops, opts),
|
|
395
|
+
storage: db.storage
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
function resolveDeps(deps) {
|
|
399
|
+
return {
|
|
400
|
+
db: readingAsWritten(deps.db),
|
|
401
|
+
now: deps.now ?? Date.now,
|
|
402
|
+
newId: deps.newId ?? (() => crypto.randomUUID()),
|
|
403
|
+
fetchBytes: deps.fetchBytes ?? defaultFetchBytes
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
|
|
361
407
|
// src/rules.ts
|
|
362
408
|
var CURRENT_BOOK_MEMBER = "ref('book.memberIds').exists(members, auth.id in members)";
|
|
363
409
|
var BRAND_RULES = {
|
|
@@ -559,7 +605,7 @@ function assertAnalysis(value) {
|
|
|
559
605
|
}
|
|
560
606
|
|
|
561
607
|
// src/review-json.ts
|
|
562
|
-
var
|
|
608
|
+
var record2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
563
609
|
function isBoundedBrandJson(root, limits = {}) {
|
|
564
610
|
const maxDepth = limits.maxDepth ?? 12;
|
|
565
611
|
const maxNodes = limits.maxNodes ?? 2048;
|
|
@@ -583,7 +629,7 @@ function isBoundedBrandJson(root, limits = {}) {
|
|
|
583
629
|
if (Array.isArray(value)) {
|
|
584
630
|
for (const child of value)
|
|
585
631
|
stack.push({ value: child, depth: depth + 1 });
|
|
586
|
-
} else if (
|
|
632
|
+
} else if (record2(value)) {
|
|
587
633
|
for (const child of Object.values(value))
|
|
588
634
|
stack.push({ value: child, depth: depth + 1 });
|
|
589
635
|
} else {
|
|
@@ -620,7 +666,7 @@ async function brandJsonDigest(value) {
|
|
|
620
666
|
|
|
621
667
|
// src/review.ts
|
|
622
668
|
var DIGEST = /^sha256:[0-9a-f]{64}$/;
|
|
623
|
-
var
|
|
669
|
+
var record3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
624
670
|
var exactKeys = (value, required, optional = []) => {
|
|
625
671
|
const allowed = /* @__PURE__ */ new Set([...required, ...optional]);
|
|
626
672
|
return required.every((key) => Object.hasOwn(value, key)) && Object.keys(value).every((key) => allowed.has(key));
|
|
@@ -645,15 +691,15 @@ var SNAPSHOT_REQUIRED = [
|
|
|
645
691
|
"createdAt"
|
|
646
692
|
];
|
|
647
693
|
function validSnapshotShape(value) {
|
|
648
|
-
if (!
|
|
694
|
+
if (!record3(value) || !exactKeys(value, SNAPSHOT_REQUIRED)) return false;
|
|
649
695
|
const provenance = value.provenance;
|
|
650
|
-
return boundedString(value.id) && boundedString(value.bookId) && typeof value.kind === "string" && PROPOSAL_KINDS.includes(value.kind) && value.status === "open" &&
|
|
696
|
+
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
697
|
"sourceAssetId",
|
|
652
698
|
"sourceAsset",
|
|
653
699
|
"messageId",
|
|
654
700
|
"turnId",
|
|
655
701
|
"taintLabels"
|
|
656
|
-
]) && (provenance.sourceAssetId === null || boundedString(provenance.sourceAssetId)) && (provenance.sourceAsset === null ||
|
|
702
|
+
]) && (provenance.sourceAssetId === null || boundedString(provenance.sourceAssetId)) && (provenance.sourceAsset === null || record3(provenance.sourceAsset) && exactKeys(provenance.sourceAsset, [
|
|
657
703
|
"assetId",
|
|
658
704
|
"contentDigest",
|
|
659
705
|
"objectEtag",
|
|
@@ -686,8 +732,8 @@ var CONSUMPTION_REQUIRED = [
|
|
|
686
732
|
"consumedAt"
|
|
687
733
|
];
|
|
688
734
|
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) &&
|
|
735
|
+
if (!record3(value) || !exactKeys(value, CONSUMPTION_REQUIRED)) return false;
|
|
736
|
+
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
737
|
}
|
|
692
738
|
var RECEIPT_REQUIRED = [
|
|
693
739
|
"version",
|
|
@@ -713,10 +759,10 @@ async function verifyBrandApprovalReceipt(receipt2) {
|
|
|
713
759
|
try {
|
|
714
760
|
if (!isBoundedBrandJson(receipt2, { maxDepth: 14, maxNodes: 2500, maxBytes: 48 * 1024 }))
|
|
715
761
|
return false;
|
|
716
|
-
if (!
|
|
762
|
+
if (!record3(receipt2) || !exactKeys(receipt2, RECEIPT_REQUIRED, ["paletteId", "resolutionNote"]))
|
|
717
763
|
return false;
|
|
718
764
|
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) || !
|
|
765
|
+
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
766
|
"version",
|
|
721
767
|
"bookVersion",
|
|
722
768
|
"activationRevision",
|
|
@@ -2481,7 +2527,7 @@ async function linkedAsset(ctx, book, assetId, allowDeleting = false) {
|
|
|
2481
2527
|
book: {}
|
|
2482
2528
|
}
|
|
2483
2529
|
});
|
|
2484
|
-
const row = (result[BRAND_NS.asset] ?? [])[0];
|
|
2530
|
+
const row = rowAsWritten(BRAND_NS.asset, (result[BRAND_NS.asset] ?? [])[0]);
|
|
2485
2531
|
const links = row?.book;
|
|
2486
2532
|
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
2533
|
return row;
|
|
@@ -2555,7 +2601,7 @@ async function loadBook(db, bookId) {
|
|
|
2555
2601
|
const res = await db.query({ [BRAND_NS.book]: { $: { where: { id: bookId } } } });
|
|
2556
2602
|
const row = (res[BRAND_NS.book] ?? [])[0];
|
|
2557
2603
|
if (!row) throw new BrandNotFoundError(`brand book ${bookId}`);
|
|
2558
|
-
return row;
|
|
2604
|
+
return rowAsWritten(BRAND_NS.book, row);
|
|
2559
2605
|
}
|
|
2560
2606
|
async function loadMemberBook(db, bookId, actorId) {
|
|
2561
2607
|
const book = await loadBook(db, bookId);
|
|
@@ -2610,14 +2656,14 @@ async function uploadAsset(ctx, req, bookId) {
|
|
|
2610
2656
|
"internal",
|
|
2611
2657
|
book.id
|
|
2612
2658
|
);
|
|
2613
|
-
const
|
|
2659
|
+
const record7 = await ctx.db.storage.upload(
|
|
2614
2660
|
path,
|
|
2615
2661
|
file,
|
|
2616
2662
|
contentType,
|
|
2617
2663
|
{ private: true }
|
|
2618
2664
|
);
|
|
2619
|
-
if (
|
|
2620
|
-
await ctx.db.storage.delete(
|
|
2665
|
+
if (record7.path !== path) {
|
|
2666
|
+
await ctx.db.storage.delete(record7.path);
|
|
2621
2667
|
throw new BrandConflictError(
|
|
2622
2668
|
"private storage returned an unexpected asset path"
|
|
2623
2669
|
);
|
|
@@ -2636,11 +2682,11 @@ async function uploadAsset(ctx, req, bookId) {
|
|
|
2636
2682
|
id,
|
|
2637
2683
|
bookId: book.id,
|
|
2638
2684
|
kind,
|
|
2639
|
-
path:
|
|
2640
|
-
storageObjectId:
|
|
2685
|
+
path: record7.path,
|
|
2686
|
+
storageObjectId: record7.id,
|
|
2641
2687
|
contentDigest: await contentDigest(file),
|
|
2642
2688
|
contentType,
|
|
2643
|
-
size:
|
|
2689
|
+
size: record7.size,
|
|
2644
2690
|
uploadedBy: ctx.actor.id,
|
|
2645
2691
|
uploadedAuthorityRef: authority.authorityRef,
|
|
2646
2692
|
audience: book.memberIds,
|
|
@@ -2667,7 +2713,7 @@ async function uploadAsset(ctx, req, bookId) {
|
|
|
2667
2713
|
asPrincipalKind: "human"
|
|
2668
2714
|
});
|
|
2669
2715
|
} catch (error) {
|
|
2670
|
-
await ctx.db.storage.delete(
|
|
2716
|
+
await ctx.db.storage.delete(record7.path);
|
|
2671
2717
|
throw error;
|
|
2672
2718
|
}
|
|
2673
2719
|
return json(await linkedAsset(ctx, book, id), 201);
|
|
@@ -2782,7 +2828,7 @@ async function handleAssetItem(ctx, req, bookId, assetId) {
|
|
|
2782
2828
|
async function handleBooksRoot(ctx, req) {
|
|
2783
2829
|
if (req.method === "GET") {
|
|
2784
2830
|
const res = await ctx.db.query({ [BRAND_NS.book]: { $: { order: { createdAt: "asc" } } } });
|
|
2785
|
-
const books = (res[BRAND_NS.book] ?? []).filter(
|
|
2831
|
+
const books = (res[BRAND_NS.book] ?? []).map((b) => rowAsWritten(BRAND_NS.book, b)).filter(
|
|
2786
2832
|
(b) => isMember(b, ctx.actor.id)
|
|
2787
2833
|
);
|
|
2788
2834
|
return json({ books });
|
|
@@ -2947,7 +2993,7 @@ var SNAPSHOT_KEYS = [
|
|
|
2947
2993
|
"reviewDigest",
|
|
2948
2994
|
"status"
|
|
2949
2995
|
];
|
|
2950
|
-
var
|
|
2996
|
+
var record4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2951
2997
|
function parseProposalResolutionRequest(body, bookId, proposalId) {
|
|
2952
2998
|
const allowed = /* @__PURE__ */ new Set([
|
|
2953
2999
|
"mutationId",
|
|
@@ -2991,13 +3037,13 @@ function proposalReviewSnapshot(proposal) {
|
|
|
2991
3037
|
function parseReviewedProposal(value, bookId, proposalId) {
|
|
2992
3038
|
if (!isBoundedBrandJson(value, { maxDepth: 12, maxNodes: 1500, maxBytes: 32 * 1024 }))
|
|
2993
3039
|
throw new BrandInputError('"reviewedProposal" is too deeply nested, complex, or large');
|
|
2994
|
-
if (!
|
|
3040
|
+
if (!record4(value)) throw new BrandInputError('"reviewedProposal" must be an object');
|
|
2995
3041
|
const keys = Object.keys(value).sort();
|
|
2996
3042
|
if (keys.length !== SNAPSHOT_KEYS.length || !SNAPSHOT_KEYS.every((key, index) => key === keys[index])) throw new BrandInputError('"reviewedProposal" has an invalid shape');
|
|
2997
3043
|
if (value.id !== proposalId || value.bookId !== bookId || value.status !== "open")
|
|
2998
3044
|
throw new BrandInputError('"reviewedProposal" must identify this open proposal');
|
|
2999
|
-
if (typeof value.kind !== "string" || !PROPOSAL_KINDS.includes(value.kind) || !
|
|
3000
|
-
if (!
|
|
3045
|
+
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');
|
|
3046
|
+
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
3047
|
value.provenance.sourceAsset.analysisDigest
|
|
3002
3048
|
)) || 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
3049
|
return value;
|
|
@@ -3170,7 +3216,7 @@ async function proposalReceiptByMutation(ctx, mutationKey) {
|
|
|
3170
3216
|
const row = (result[BRAND_NS.approvalReceipt] ?? [])[0];
|
|
3171
3217
|
if (!row || !Array.isArray(row.book) || row.book.length !== 1 || row.book[0]?.id !== row.bookId) return void 0;
|
|
3172
3218
|
const { book: _book, ...receipt2 } = row;
|
|
3173
|
-
return receipt2;
|
|
3219
|
+
return receiptAsWritten(receipt2);
|
|
3174
3220
|
}
|
|
3175
3221
|
async function consumeProposalAuthority(ctx, req, bookId, proposalId, actionDigest, mutationKey) {
|
|
3176
3222
|
const authority = await ctx.consumeHumanExact({
|
|
@@ -3204,7 +3250,8 @@ async function receipt(ctx, id, actionDigest, expected) {
|
|
|
3204
3250
|
});
|
|
3205
3251
|
const row = (result[BRAND_NS.approvalReceipt] ?? [])[0];
|
|
3206
3252
|
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, ...
|
|
3253
|
+
const { book: _book, ...stored } = row;
|
|
3254
|
+
const unhydrated = receiptAsWritten(stored);
|
|
3208
3255
|
if (!await verifyBrandApprovalReceipt(unhydrated))
|
|
3209
3256
|
throw new BrandConflictError(`approval receipt ${id} is invalid`);
|
|
3210
3257
|
return unhydrated;
|
|
@@ -3442,9 +3489,9 @@ async function proposalDecisionState(ctx, req, book, proposal, resolution, recei
|
|
|
3442
3489
|
}
|
|
3443
3490
|
|
|
3444
3491
|
// src/routes/proposals.ts
|
|
3445
|
-
var
|
|
3492
|
+
var record5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3446
3493
|
var sameStrings2 = (left, right) => left.length === right.length && left.every((value, index) => value === right[index]);
|
|
3447
|
-
var guardFailure2 = (error) =>
|
|
3494
|
+
var guardFailure2 = (error) => record5(error) && error.code === "transact_guard_failed";
|
|
3448
3495
|
async function handleProposalResolution(ctx, req, bookId, proposalId) {
|
|
3449
3496
|
if (req.method !== "POST") return methodNotAllowed();
|
|
3450
3497
|
const book = await loadMemberBook(ctx.db, bookId, ctx.actor.id);
|
|
@@ -3491,7 +3538,7 @@ async function handleProposalResolution(ctx, req, bookId, proposalId) {
|
|
|
3491
3538
|
book: {}
|
|
3492
3539
|
}
|
|
3493
3540
|
});
|
|
3494
|
-
const proposal = (result[BRAND_NS.proposal] ?? [])[0];
|
|
3541
|
+
const proposal = proposalAsWritten((result[BRAND_NS.proposal] ?? [])[0]);
|
|
3495
3542
|
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
3543
|
const current = proposalReviewSnapshot(proposal);
|
|
3497
3544
|
const { reviewDigest, ...unsignedReview } = current;
|
|
@@ -3624,7 +3671,7 @@ async function handleProposalResolution(ctx, req, bookId, proposalId) {
|
|
|
3624
3671
|
}
|
|
3625
3672
|
|
|
3626
3673
|
// src/routes/tokens.ts
|
|
3627
|
-
var
|
|
3674
|
+
var record6 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3628
3675
|
var missing = (bookId) => {
|
|
3629
3676
|
throw new BrandNotFoundError(`compiled tokens for brand book ${bookId}`);
|
|
3630
3677
|
};
|
|
@@ -3637,13 +3684,14 @@ async function acceptedReceipt(db, bookId, receiptId, actionDigest) {
|
|
|
3637
3684
|
});
|
|
3638
3685
|
const receipt2 = (result[BRAND_NS.approvalReceipt] ?? [])[0];
|
|
3639
3686
|
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, ...
|
|
3687
|
+
const { book: _book, ...stored } = receipt2;
|
|
3688
|
+
const unhydrated = receiptAsWritten(stored);
|
|
3641
3689
|
if (!await verifyBrandApprovalReceipt(unhydrated)) return missing(bookId);
|
|
3642
3690
|
return unhydrated;
|
|
3643
3691
|
}
|
|
3644
3692
|
async function approvedCache(db, book) {
|
|
3645
3693
|
const cache = book.tokens;
|
|
3646
|
-
if (!cache || !
|
|
3694
|
+
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
3695
|
const paletteResult = await db.query({
|
|
3648
3696
|
[BRAND_NS.palette]: {
|
|
3649
3697
|
$: { where: { id: cache.paletteId, bookId: book.id } },
|
|
@@ -4427,11 +4475,13 @@ export {
|
|
|
4427
4475
|
parseDesignBundle,
|
|
4428
4476
|
parseHex,
|
|
4429
4477
|
pickTextOn,
|
|
4478
|
+
proposalAsWritten,
|
|
4430
4479
|
proposalReviewSnapshot,
|
|
4431
4480
|
proposePaletteOps,
|
|
4432
4481
|
proposeSectionOps,
|
|
4433
4482
|
readDesignManifest,
|
|
4434
4483
|
readTools,
|
|
4484
|
+
receiptAsWritten,
|
|
4435
4485
|
recordAnalysisOps,
|
|
4436
4486
|
rejectProposalOps,
|
|
4437
4487
|
relativeLuminance,
|
|
@@ -4441,6 +4491,7 @@ export {
|
|
|
4441
4491
|
rgbToHsl,
|
|
4442
4492
|
rgbToOklab,
|
|
4443
4493
|
rotateHue,
|
|
4494
|
+
rowAsWritten,
|
|
4444
4495
|
safeFileName,
|
|
4445
4496
|
scanCustomProperties,
|
|
4446
4497
|
sectionKey,
|