multicorn-shield 0.10.0 → 0.12.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/CHANGELOG.md CHANGED
@@ -5,6 +5,46 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [X.Y.Z] - YYYY-MM-DD
9
+
10
+ ### Added
11
+
12
+ - Cline native plugin support via PreToolUse/PostToolUse hooks
13
+ - Hook scripts for Cline: pre-tool-use.cjs, post-tool-use.cjs, shared.cjs
14
+ - Cline plugin README with setup instructions and troubleshooting
15
+ - Browser auto-open for consent screen when Shield blocks an action
16
+ - Licence headers on all plugin scripts
17
+
18
+ ### Changed
19
+
20
+ - CLI wizard installs Cline hooks to ~/Documents/Cline/Hooks/ (previously ~/Documents/Cline/Rules/Hooks/)
21
+ - Cline hook reads toolName field from hook input (Cline v3.81+ sends toolName, not tool)
22
+ - Consent flow no longer polls for approval (blocks immediately with consent URL to avoid Cline's 30-second hook timeout)
23
+ - Extracted shared utilities (config loading, HTTP, tool mapping) into shared.cjs to eliminate duplication between hooks
24
+ - Parameter metadata scrubbed before sending to Shield API (file contents redacted, commands truncated)
25
+ - HTTPS enforced for non-local Shield API connections
26
+
27
+ ### Removed
28
+
29
+ - Polling-based consent approval flow (replaced with immediate block + consent URL)
30
+ - Consent marker filesystem state (no longer needed without polling)
31
+
32
+ ### Security
33
+
34
+ - Fixed Windows shell injection in openBrowser (replaced execSync with execFileSync)
35
+ - Added HTTPS enforcement for non-localhost baseUrl in hook config
36
+ - Added parameter and result scrubbing to prevent sensitive data leakage in audit metadata
37
+
38
+ ## [0.11.0] - 2026-04-25
39
+
40
+ ### Added
41
+
42
+ - `<multicorn-badge>` trust badge web component for embedding in third-party products. Shadow DOM encapsulation, dark/light themes, compact/standard sizes, optional action count display.
43
+ - CDN entrypoint (`dist/badge.js`) for single-script-tag embedding: `<script src="https://cdn.multicorn.ai/badge.js" data-agent-id="..."></script>`. Self-contained, no Lit runtime dependency.
44
+ - `MulticornBadge` class exported from the main SDK barrel for programmatic usage.
45
+ - Shared `shield-tokens.ts` module (`src/shared/`) extracting `SHIELD_COLORS` design tokens for reuse across consent and badge components.
46
+ - `size-limit` budget enforcement for `dist/badge.js` at 5 kB gzip (actual ~1.75 kB).
47
+
8
48
  ## [0.10.0] - 2026-04-21
9
49
 
10
50
  ### Added
package/dist/badge.js ADDED
@@ -0,0 +1,44 @@
1
+ var n={surface:"#14141f",surfaceHover:"#1a1a2e",border:"#2a2a3d",text:"#e8e8f0",accent:"#8b5cf6",accentDim:"rgba(139, 92, 246, 0.12)"};var E="#0f172a",y="#f8fafc",L="#f1f5f9",A="#e2e8f0";function h(){return `
2
+ :host { display: inline-block; line-height: 0; }
3
+ .badge {
4
+ display: inline-flex;
5
+ align-items: center;
6
+ justify-content: center;
7
+ box-sizing: border-box;
8
+ gap: 6px;
9
+ min-height: 28px;
10
+ padding: 4px 10px 4px 8px;
11
+ border-radius: 9999px;
12
+ text-decoration: none;
13
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
14
+ font-size: 12px;
15
+ font-weight: 500;
16
+ border: 1px solid ${n.border};
17
+ background: ${n.surface};
18
+ color: ${n.text};
19
+ transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
20
+ }
21
+ :host([theme="light"]) .badge {
22
+ border-color: ${A};
23
+ background: ${y};
24
+ color: ${E};
25
+ }
26
+ .badge:hover {
27
+ background: ${n.surfaceHover};
28
+ border-color: ${n.accent};
29
+ box-shadow: 0 0 0 1px ${n.accentDim};
30
+ }
31
+ :host([theme="light"]) .badge:hover {
32
+ background: ${L};
33
+ border-color: ${n.accent};
34
+ }
35
+ .badge:focus-visible {
36
+ outline: 2px solid ${n.accent};
37
+ outline-offset: 2px;
38
+ }
39
+ .icon { flex-shrink: 0; display: block; }
40
+ .text { white-space: nowrap; }
41
+ :host([size="compact"]) .text { display: none; }
42
+ :host([size="compact"]) .badge { padding: 4px 6px; }
43
+ @media (prefers-reduced-motion: reduce) { .badge { transition: none; } }
44
+ `.trim()}var T="https://multicorn.ai/verify/",x="multicorn-badge",v="M12 1L3 5v6c0 5.55 3.84 9.95 9 12 5.16-2.05 9-6.45 9-12V5l-9-4z",w=typeof HTMLElement<"u"?HTMLElement:class{connectedCallback(){}};function C(e){if(e==null||e==="")return;let t=Number(e);return Number.isNaN(t)?void 0:t}var m=class extends w{#e=false;ensureShadow(){return this.shadowRoot!=null?this.shadowRoot:this.attachShadow({mode:"open"})}static get observedAttributes(){return ["agent-id","size","theme","action-count"]}connectedCallback(){this.render();}attributeChangedCallback(){this.render();}render(){let t=this.ensureShadow();if(!this.#e){let g=document.createElement("style");g.textContent=h(),t.appendChild(g),this.#e=true;}let s=(this.getAttribute("agent-id")??"").trim(),c=C(this.getAttribute("action-count")),a=t.querySelector("a.badge");if(a&&a.remove(),s==="")return;let d,l;if(c==null)d="Secured by Multicorn",l="Secured by Multicorn, verify this agent";else {let f=String(c);d="Secured by Multicorn \xB7 "+f+" actions secured",l="Secured by Multicorn \xB7 "+f+" actions secured, verify this agent";}let S=`${T}${encodeURIComponent(s)}`,o=document.createElement("a");o.className="badge",o.href=S,o.target="_blank",o.rel="noopener noreferrer",o.setAttribute("aria-label",l);let p="http://www.w3.org/2000/svg",r=document.createElementNS(p,"svg");r.setAttribute("class","icon"),r.setAttribute("width","16"),r.setAttribute("height","16"),r.setAttribute("viewBox","0 0 24 24"),r.setAttribute("aria-hidden","true");let u=document.createElementNS(p,"path");u.setAttribute("d",v),u.setAttribute("fill",n.accent),r.appendChild(u),o.appendChild(r);let b=document.createElement("span");b.className="text",b.textContent=d,o.appendChild(b),t.appendChild(o);}};typeof customElements<"u"&&customElements.get(x)===void 0&&customElements.define(x,m);function H(e){return e==="compact"||e==="standard"}function M(e){return e==="dark"||e==="light"}var i=(typeof document<"u"&&document.currentScript!==null?document.currentScript:null)??null;if(i==null)console.warn("[Multicorn] badge.js must be loaded as a classic script (document.currentScript was null).");else {let e=i.dataset.agentId?.trim();if(e==null||e==="")console.warn("[Multicorn] Skipping trust badge: missing data-agent-id on the badge script tag.");else {let t=document.createElement("multicorn-badge");t.setAttribute("agent-id",e);let s=i.dataset.size;H(s)&&t.setAttribute("size",s);let c=i.dataset.theme;M(c)&&t.setAttribute("theme",c);let a=i.dataset.actionCount;a!=null&&a!==""&&t.setAttribute("action-count",a),i.parentNode?.insertBefore(t,i.nextSibling);}}
package/dist/index.cjs CHANGED
@@ -4,13 +4,12 @@ var lit = require('lit');
4
4
  var decorators_js = require('lit/decorators.js');
5
5
 
6
6
  var __defProp = Object.defineProperty;
7
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
8
7
  var __decorateClass = (decorators, target, key, kind) => {
9
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
8
+ var result = void 0 ;
10
9
  for (var i = decorators.length - 1, decorator; i >= 0; i--)
11
10
  if (decorator = decorators[i])
12
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
13
- if (kind && result) __defProp(target, key, result);
11
+ result = (decorator(target, key, result) ) || result;
12
+ if (result) __defProp(target, key, result);
14
13
  return result;
15
14
  };
16
15
 
@@ -432,6 +431,8 @@ function getScopeWarning(scopeString) {
432
431
  const metadata = getScopeMetadata(scopeString);
433
432
  return metadata?.warningMessage;
434
433
  }
434
+
435
+ // src/shared/shield-tokens.ts
435
436
  var SHIELD_COLORS = {
436
437
  bg: "#0d0d14",
437
438
  surface: "#14141f",
@@ -452,6 +453,8 @@ var SHIELD_COLORS = {
452
453
  red: "#ef4444",
453
454
  redDim: "rgba(239, 68, 68, 0.12)"
454
455
  };
456
+
457
+ // src/consent/consent-styles.ts
455
458
  var consentStyles = lit.css`
456
459
  :host {
457
460
  display: block;
@@ -1124,7 +1127,7 @@ function groupScopesByService(scopes) {
1124
1127
  function scopeKey(scope) {
1125
1128
  return `${scope.service}:${scope.permissionLevel}`;
1126
1129
  }
1127
- exports.MulticornConsent = class MulticornConsent extends lit.LitElement {
1130
+ var MulticornConsent = class extends lit.LitElement {
1128
1131
  constructor() {
1129
1132
  super(...arguments);
1130
1133
  this.agentName = "";
@@ -1197,6 +1200,9 @@ exports.MulticornConsent = class MulticornConsent extends lit.LitElement {
1197
1200
  }
1198
1201
  };
1199
1202
  }
1203
+ static {
1204
+ this.styles = [consentStyles];
1205
+ }
1200
1206
  connectedCallback() {
1201
1207
  super.connectedCallback();
1202
1208
  if (Array.isArray(this.scopes) && this.scopes.length > 0) {
@@ -1570,34 +1576,175 @@ exports.MulticornConsent = class MulticornConsent extends lit.LitElement {
1570
1576
  this.requestUpdate();
1571
1577
  }
1572
1578
  };
1573
- exports.MulticornConsent.styles = [consentStyles];
1574
1579
  __decorateClass([
1575
1580
  decorators_js.property({ type: String, attribute: "agent-name" })
1576
- ], exports.MulticornConsent.prototype, "agentName", 2);
1581
+ ], MulticornConsent.prototype, "agentName");
1577
1582
  __decorateClass([
1578
1583
  decorators_js.property({ type: String, attribute: "agent-color" })
1579
- ], exports.MulticornConsent.prototype, "agentColor", 2);
1584
+ ], MulticornConsent.prototype, "agentColor");
1580
1585
  __decorateClass([
1581
1586
  decorators_js.property({ type: Array, attribute: "scopes" })
1582
- ], exports.MulticornConsent.prototype, "scopes", 2);
1587
+ ], MulticornConsent.prototype, "scopes");
1583
1588
  __decorateClass([
1584
1589
  decorators_js.property({ type: Number, attribute: "spend-limit" })
1585
- ], exports.MulticornConsent.prototype, "spendLimit", 2);
1590
+ ], MulticornConsent.prototype, "spendLimit");
1586
1591
  __decorateClass([
1587
1592
  decorators_js.property({ type: String })
1588
- ], exports.MulticornConsent.prototype, "mode", 2);
1593
+ ], MulticornConsent.prototype, "mode");
1589
1594
  __decorateClass([
1590
1595
  decorators_js.state()
1591
- ], exports.MulticornConsent.prototype, "_grantedScopes", 2);
1596
+ ], MulticornConsent.prototype, "_grantedScopes");
1592
1597
  __decorateClass([
1593
1598
  decorators_js.state()
1594
- ], exports.MulticornConsent.prototype, "_adjustedSpendLimit", 2);
1599
+ ], MulticornConsent.prototype, "_adjustedSpendLimit");
1595
1600
  __decorateClass([
1596
1601
  decorators_js.state()
1597
- ], exports.MulticornConsent.prototype, "_isOpen", 2);
1598
- exports.MulticornConsent = __decorateClass([
1599
- decorators_js.customElement(CONSENT_ELEMENT_TAG)
1600
- ], exports.MulticornConsent);
1602
+ ], MulticornConsent.prototype, "_isOpen");
1603
+ if (typeof customElements !== "undefined" && customElements.get(CONSENT_ELEMENT_TAG) === void 0) {
1604
+ customElements.define(CONSENT_ELEMENT_TAG, MulticornConsent);
1605
+ }
1606
+
1607
+ // src/badge/badge-styles.ts
1608
+ var LIGHT_TEXT = "#0f172a";
1609
+ var LIGHT_SURFACE = "#f8fafc";
1610
+ var LIGHT_SURFACE_HOVER = "#f1f5f9";
1611
+ var LIGHT_BORDER = "#e2e8f0";
1612
+ function getBadgeStyleText() {
1613
+ return `
1614
+ :host { display: inline-block; line-height: 0; }
1615
+ .badge {
1616
+ display: inline-flex;
1617
+ align-items: center;
1618
+ justify-content: center;
1619
+ box-sizing: border-box;
1620
+ gap: 6px;
1621
+ min-height: 28px;
1622
+ padding: 4px 10px 4px 8px;
1623
+ border-radius: 9999px;
1624
+ text-decoration: none;
1625
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
1626
+ font-size: 12px;
1627
+ font-weight: 500;
1628
+ border: 1px solid ${SHIELD_COLORS.border};
1629
+ background: ${SHIELD_COLORS.surface};
1630
+ color: ${SHIELD_COLORS.text};
1631
+ transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
1632
+ }
1633
+ :host([theme="light"]) .badge {
1634
+ border-color: ${LIGHT_BORDER};
1635
+ background: ${LIGHT_SURFACE};
1636
+ color: ${LIGHT_TEXT};
1637
+ }
1638
+ .badge:hover {
1639
+ background: ${SHIELD_COLORS.surfaceHover};
1640
+ border-color: ${SHIELD_COLORS.accent};
1641
+ box-shadow: 0 0 0 1px ${SHIELD_COLORS.accentDim};
1642
+ }
1643
+ :host([theme="light"]) .badge:hover {
1644
+ background: ${LIGHT_SURFACE_HOVER};
1645
+ border-color: ${SHIELD_COLORS.accent};
1646
+ }
1647
+ .badge:focus-visible {
1648
+ outline: 2px solid ${SHIELD_COLORS.accent};
1649
+ outline-offset: 2px;
1650
+ }
1651
+ .icon { flex-shrink: 0; display: block; }
1652
+ .text { white-space: nowrap; }
1653
+ :host([size="compact"]) .text { display: none; }
1654
+ :host([size="compact"]) .badge { padding: 4px 6px; }
1655
+ @media (prefers-reduced-motion: reduce) { .badge { transition: none; } }
1656
+ `.trim();
1657
+ }
1658
+
1659
+ // src/badge/multicorn-badge.ts
1660
+ var VERIFY_BASE = "https://multicorn.ai/verify/";
1661
+ var BADGE_ELEMENT_TAG = "multicorn-badge";
1662
+ var SHIELD_PATH = "M12 1L3 5v6c0 5.55 3.84 9.95 9 12 5.16-2.05 9-6.45 9-12V5l-9-4z";
1663
+ var SafeHTMLElement = typeof HTMLElement !== "undefined" ? HTMLElement : class {
1664
+ connectedCallback() {
1665
+ }
1666
+ };
1667
+ function parseOptionalCount(raw) {
1668
+ if (raw == null || raw === "") {
1669
+ return void 0;
1670
+ }
1671
+ const n = Number(raw);
1672
+ return Number.isNaN(n) ? void 0 : n;
1673
+ }
1674
+ var MulticornBadge = class extends SafeHTMLElement {
1675
+ #didInjectStyle = false;
1676
+ ensureShadow() {
1677
+ if (this.shadowRoot != null) {
1678
+ return this.shadowRoot;
1679
+ }
1680
+ return this.attachShadow({ mode: "open" });
1681
+ }
1682
+ static get observedAttributes() {
1683
+ return ["agent-id", "size", "theme", "action-count"];
1684
+ }
1685
+ connectedCallback() {
1686
+ this.render();
1687
+ }
1688
+ attributeChangedCallback() {
1689
+ this.render();
1690
+ }
1691
+ render() {
1692
+ const root = this.ensureShadow();
1693
+ if (this.#didInjectStyle) ; else {
1694
+ const style = document.createElement("style");
1695
+ style.textContent = getBadgeStyleText();
1696
+ root.appendChild(style);
1697
+ this.#didInjectStyle = true;
1698
+ }
1699
+ const agentId = (this.getAttribute("agent-id") ?? "").trim();
1700
+ const actionCount = parseOptionalCount(this.getAttribute("action-count"));
1701
+ const prior = root.querySelector("a.badge");
1702
+ if (prior) {
1703
+ prior.remove();
1704
+ }
1705
+ if (agentId === "") {
1706
+ return;
1707
+ }
1708
+ let labelSuffix;
1709
+ let ariaLabel;
1710
+ if (actionCount == null) {
1711
+ labelSuffix = "Secured by Multicorn";
1712
+ ariaLabel = "Secured by Multicorn, verify this agent";
1713
+ } else {
1714
+ const count = actionCount;
1715
+ const countText = String(count);
1716
+ labelSuffix = "Secured by Multicorn \xB7 " + countText + " actions secured";
1717
+ ariaLabel = "Secured by Multicorn \xB7 " + countText + " actions secured, verify this agent";
1718
+ }
1719
+ const href = `${VERIFY_BASE}${encodeURIComponent(agentId)}`;
1720
+ const a = document.createElement("a");
1721
+ a.className = "badge";
1722
+ a.href = href;
1723
+ a.target = "_blank";
1724
+ a.rel = "noopener noreferrer";
1725
+ a.setAttribute("aria-label", ariaLabel);
1726
+ const svgNs = "http://www.w3.org/2000/svg";
1727
+ const svg = document.createElementNS(svgNs, "svg");
1728
+ svg.setAttribute("class", "icon");
1729
+ svg.setAttribute("width", "16");
1730
+ svg.setAttribute("height", "16");
1731
+ svg.setAttribute("viewBox", "0 0 24 24");
1732
+ svg.setAttribute("aria-hidden", "true");
1733
+ const path = document.createElementNS(svgNs, "path");
1734
+ path.setAttribute("d", SHIELD_PATH);
1735
+ path.setAttribute("fill", SHIELD_COLORS.accent);
1736
+ svg.appendChild(path);
1737
+ a.appendChild(svg);
1738
+ const text = document.createElement("span");
1739
+ text.className = "text";
1740
+ text.textContent = labelSuffix;
1741
+ a.appendChild(text);
1742
+ root.appendChild(a);
1743
+ }
1744
+ };
1745
+ if (typeof customElements !== "undefined" && customElements.get(BADGE_ELEMENT_TAG) === void 0) {
1746
+ customElements.define(BADGE_ELEMENT_TAG, MulticornBadge);
1747
+ }
1601
1748
 
1602
1749
  // src/logger/action-logger.ts
1603
1750
  function createActionLogger(config) {
@@ -2749,6 +2896,8 @@ exports.ACTION_STATUSES = ACTION_STATUSES;
2749
2896
  exports.AGENT_STATUSES = AGENT_STATUSES;
2750
2897
  exports.BUILT_IN_SERVICES = BUILT_IN_SERVICES;
2751
2898
  exports.CONSENT_ELEMENT_TAG = CONSENT_ELEMENT_TAG;
2899
+ exports.MulticornBadge = MulticornBadge;
2900
+ exports.MulticornConsent = MulticornConsent;
2752
2901
  exports.MulticornShield = MulticornShield;
2753
2902
  exports.PERMISSION_LEVELS = PERMISSION_LEVELS;
2754
2903
  exports.SERVICE_NAME_PATTERN = SERVICE_NAME_PATTERN;
package/dist/index.d.cts CHANGED
@@ -1069,6 +1069,33 @@ interface FocusTrap {
1069
1069
  */
1070
1070
  declare function createFocusTrap(container: HTMLElement, initialFocus?: HTMLElement | null): FocusTrap;
1071
1071
 
1072
+ /**
1073
+ * `<multicorn-badge>`: small embeddable trust badge (Shadow DOM).
1074
+ * Implemented as a native custom element to keep the CDN `badge.js` under the
1075
+ * size budget. Styling and tokens align with the Lit-based consent screen.
1076
+ *
1077
+ * @module badge/multicorn-badge
1078
+ */
1079
+ /** Custom element tag for the trust badge. */
1080
+ declare const BADGE_ELEMENT_TAG: "multicorn-badge";
1081
+ declare const SafeHTMLElement: {
1082
+ new (): HTMLElement;
1083
+ prototype: HTMLElement;
1084
+ };
1085
+ declare class MulticornBadge extends SafeHTMLElement {
1086
+ #private;
1087
+ private ensureShadow;
1088
+ static get observedAttributes(): string[];
1089
+ connectedCallback(): void;
1090
+ attributeChangedCallback(): void;
1091
+ private render;
1092
+ }
1093
+ declare global {
1094
+ interface HTMLElementTagNameMap {
1095
+ [BADGE_ELEMENT_TAG]: MulticornBadge;
1096
+ }
1097
+ }
1098
+
1072
1099
  /**
1073
1100
  * Action logging client for Multicorn Shield.
1074
1101
  *
@@ -2283,4 +2310,4 @@ interface ContentReviewRequestPayload {
2283
2310
  */
2284
2311
  declare function requestContentReview(payload: ContentReviewRequestPayload, apiKey: string, baseUrl: string, logger?: PluginLogger): Promise<ContentReviewResult>;
2285
2312
 
2286
- export { ACTION_STATUSES, AGENT_STATUSES, type Action, type ActionInput, type ActionLogger, type ActionLoggerConfig, type ActionPayload, type ActionStatus, type Agent, type AgentStatus, type ApiError, BUILT_IN_SERVICES, type BatchModeConfig, type BuiltInServiceName, CONSENT_ELEMENT_TAG, type ConsentDecision, type ConsentDeniedEventDetail, type ConsentEventDetail, type ConsentEventMap, type ConsentEventName, type ConsentGrantedEventDetail, type ConsentOptions, type ConsentPartialEventDetail, type ContentReviewRequestPayload, type ContentReviewResult, type ContentReviewStatusResponse, type FocusTrap, type McpAdapter, type McpAdapterConfig, type McpAdapterResult, type McpBlockedResult, type McpToolCall, type McpToolHandler, type McpToolResult, MulticornConsent, MulticornShield, type MulticornShieldConfig, PERMISSION_LEVELS, type Permission, type PermissionLevel, type RemainingBudget, SERVICE_NAME_PATTERN, type Scope, ScopeParseError, type ScopeParseResult, type ScopeRegistry, type ScopeRequest, type ServiceDefinition, type SpendCheckResult, type SpendingCheckResult, type SpendingChecker, type SpendingLimit, type SpendingLimits, type SpendingTrackerConfig, type ValidationResult, centsToDollars, createActionLogger, createFocusTrap, createMcpAdapter, createScopeRegistry, createSpendingChecker, dollarsToCents, formatScope, getPermissionLabel, getScopeLabel, getScopeShortLabel, getServiceDisplayName, getServiceIcon, hasScope, isBlockedResult, isPublicContentAction, isValidScopeString, parseScope, parseScopes, requestContentReview, requiresContentReview, tryParseScope, validateAllScopesAccess, validateScopeAccess };
2313
+ export { ACTION_STATUSES, AGENT_STATUSES, type Action, type ActionInput, type ActionLogger, type ActionLoggerConfig, type ActionPayload, type ActionStatus, type Agent, type AgentStatus, type ApiError, BUILT_IN_SERVICES, type BatchModeConfig, type BuiltInServiceName, CONSENT_ELEMENT_TAG, type ConsentDecision, type ConsentDeniedEventDetail, type ConsentEventDetail, type ConsentEventMap, type ConsentEventName, type ConsentGrantedEventDetail, type ConsentOptions, type ConsentPartialEventDetail, type ContentReviewRequestPayload, type ContentReviewResult, type ContentReviewStatusResponse, type FocusTrap, type McpAdapter, type McpAdapterConfig, type McpAdapterResult, type McpBlockedResult, type McpToolCall, type McpToolHandler, type McpToolResult, MulticornBadge, MulticornConsent, MulticornShield, type MulticornShieldConfig, PERMISSION_LEVELS, type Permission, type PermissionLevel, type RemainingBudget, SERVICE_NAME_PATTERN, type Scope, ScopeParseError, type ScopeParseResult, type ScopeRegistry, type ScopeRequest, type ServiceDefinition, type SpendCheckResult, type SpendingCheckResult, type SpendingChecker, type SpendingLimit, type SpendingLimits, type SpendingTrackerConfig, type ValidationResult, centsToDollars, createActionLogger, createFocusTrap, createMcpAdapter, createScopeRegistry, createSpendingChecker, dollarsToCents, formatScope, getPermissionLabel, getScopeLabel, getScopeShortLabel, getServiceDisplayName, getServiceIcon, hasScope, isBlockedResult, isPublicContentAction, isValidScopeString, parseScope, parseScopes, requestContentReview, requiresContentReview, tryParseScope, validateAllScopesAccess, validateScopeAccess };
package/dist/index.d.ts CHANGED
@@ -1069,6 +1069,33 @@ interface FocusTrap {
1069
1069
  */
1070
1070
  declare function createFocusTrap(container: HTMLElement, initialFocus?: HTMLElement | null): FocusTrap;
1071
1071
 
1072
+ /**
1073
+ * `<multicorn-badge>`: small embeddable trust badge (Shadow DOM).
1074
+ * Implemented as a native custom element to keep the CDN `badge.js` under the
1075
+ * size budget. Styling and tokens align with the Lit-based consent screen.
1076
+ *
1077
+ * @module badge/multicorn-badge
1078
+ */
1079
+ /** Custom element tag for the trust badge. */
1080
+ declare const BADGE_ELEMENT_TAG: "multicorn-badge";
1081
+ declare const SafeHTMLElement: {
1082
+ new (): HTMLElement;
1083
+ prototype: HTMLElement;
1084
+ };
1085
+ declare class MulticornBadge extends SafeHTMLElement {
1086
+ #private;
1087
+ private ensureShadow;
1088
+ static get observedAttributes(): string[];
1089
+ connectedCallback(): void;
1090
+ attributeChangedCallback(): void;
1091
+ private render;
1092
+ }
1093
+ declare global {
1094
+ interface HTMLElementTagNameMap {
1095
+ [BADGE_ELEMENT_TAG]: MulticornBadge;
1096
+ }
1097
+ }
1098
+
1072
1099
  /**
1073
1100
  * Action logging client for Multicorn Shield.
1074
1101
  *
@@ -2283,4 +2310,4 @@ interface ContentReviewRequestPayload {
2283
2310
  */
2284
2311
  declare function requestContentReview(payload: ContentReviewRequestPayload, apiKey: string, baseUrl: string, logger?: PluginLogger): Promise<ContentReviewResult>;
2285
2312
 
2286
- export { ACTION_STATUSES, AGENT_STATUSES, type Action, type ActionInput, type ActionLogger, type ActionLoggerConfig, type ActionPayload, type ActionStatus, type Agent, type AgentStatus, type ApiError, BUILT_IN_SERVICES, type BatchModeConfig, type BuiltInServiceName, CONSENT_ELEMENT_TAG, type ConsentDecision, type ConsentDeniedEventDetail, type ConsentEventDetail, type ConsentEventMap, type ConsentEventName, type ConsentGrantedEventDetail, type ConsentOptions, type ConsentPartialEventDetail, type ContentReviewRequestPayload, type ContentReviewResult, type ContentReviewStatusResponse, type FocusTrap, type McpAdapter, type McpAdapterConfig, type McpAdapterResult, type McpBlockedResult, type McpToolCall, type McpToolHandler, type McpToolResult, MulticornConsent, MulticornShield, type MulticornShieldConfig, PERMISSION_LEVELS, type Permission, type PermissionLevel, type RemainingBudget, SERVICE_NAME_PATTERN, type Scope, ScopeParseError, type ScopeParseResult, type ScopeRegistry, type ScopeRequest, type ServiceDefinition, type SpendCheckResult, type SpendingCheckResult, type SpendingChecker, type SpendingLimit, type SpendingLimits, type SpendingTrackerConfig, type ValidationResult, centsToDollars, createActionLogger, createFocusTrap, createMcpAdapter, createScopeRegistry, createSpendingChecker, dollarsToCents, formatScope, getPermissionLabel, getScopeLabel, getScopeShortLabel, getServiceDisplayName, getServiceIcon, hasScope, isBlockedResult, isPublicContentAction, isValidScopeString, parseScope, parseScopes, requestContentReview, requiresContentReview, tryParseScope, validateAllScopesAccess, validateScopeAccess };
2313
+ export { ACTION_STATUSES, AGENT_STATUSES, type Action, type ActionInput, type ActionLogger, type ActionLoggerConfig, type ActionPayload, type ActionStatus, type Agent, type AgentStatus, type ApiError, BUILT_IN_SERVICES, type BatchModeConfig, type BuiltInServiceName, CONSENT_ELEMENT_TAG, type ConsentDecision, type ConsentDeniedEventDetail, type ConsentEventDetail, type ConsentEventMap, type ConsentEventName, type ConsentGrantedEventDetail, type ConsentOptions, type ConsentPartialEventDetail, type ContentReviewRequestPayload, type ContentReviewResult, type ContentReviewStatusResponse, type FocusTrap, type McpAdapter, type McpAdapterConfig, type McpAdapterResult, type McpBlockedResult, type McpToolCall, type McpToolHandler, type McpToolResult, MulticornBadge, MulticornConsent, MulticornShield, type MulticornShieldConfig, PERMISSION_LEVELS, type Permission, type PermissionLevel, type RemainingBudget, SERVICE_NAME_PATTERN, type Scope, ScopeParseError, type ScopeParseResult, type ScopeRegistry, type ScopeRequest, type ServiceDefinition, type SpendCheckResult, type SpendingCheckResult, type SpendingChecker, type SpendingLimit, type SpendingLimits, type SpendingTrackerConfig, type ValidationResult, centsToDollars, createActionLogger, createFocusTrap, createMcpAdapter, createScopeRegistry, createSpendingChecker, dollarsToCents, formatScope, getPermissionLabel, getScopeLabel, getScopeShortLabel, getServiceDisplayName, getServiceIcon, hasScope, isBlockedResult, isPublicContentAction, isValidScopeString, parseScope, parseScopes, requestContentReview, requiresContentReview, tryParseScope, validateAllScopesAccess, validateScopeAccess };
package/dist/index.js CHANGED
@@ -1,14 +1,13 @@
1
1
  import { unsafeCSS, css, LitElement, html } from 'lit';
2
- import { property, state, customElement } from 'lit/decorators.js';
2
+ import { property, state } from 'lit/decorators.js';
3
3
 
4
4
  var __defProp = Object.defineProperty;
5
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
5
  var __decorateClass = (decorators, target, key, kind) => {
7
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
6
+ var result = void 0 ;
8
7
  for (var i = decorators.length - 1, decorator; i >= 0; i--)
9
8
  if (decorator = decorators[i])
10
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
11
- if (kind && result) __defProp(target, key, result);
9
+ result = (decorator(target, key, result) ) || result;
10
+ if (result) __defProp(target, key, result);
12
11
  return result;
13
12
  };
14
13
 
@@ -430,6 +429,8 @@ function getScopeWarning(scopeString) {
430
429
  const metadata = getScopeMetadata(scopeString);
431
430
  return metadata?.warningMessage;
432
431
  }
432
+
433
+ // src/shared/shield-tokens.ts
433
434
  var SHIELD_COLORS = {
434
435
  bg: "#0d0d14",
435
436
  surface: "#14141f",
@@ -450,6 +451,8 @@ var SHIELD_COLORS = {
450
451
  red: "#ef4444",
451
452
  redDim: "rgba(239, 68, 68, 0.12)"
452
453
  };
454
+
455
+ // src/consent/consent-styles.ts
453
456
  var consentStyles = css`
454
457
  :host {
455
458
  display: block;
@@ -1195,6 +1198,9 @@ var MulticornConsent = class extends LitElement {
1195
1198
  }
1196
1199
  };
1197
1200
  }
1201
+ static {
1202
+ this.styles = [consentStyles];
1203
+ }
1198
1204
  connectedCallback() {
1199
1205
  super.connectedCallback();
1200
1206
  if (Array.isArray(this.scopes) && this.scopes.length > 0) {
@@ -1568,34 +1574,175 @@ var MulticornConsent = class extends LitElement {
1568
1574
  this.requestUpdate();
1569
1575
  }
1570
1576
  };
1571
- MulticornConsent.styles = [consentStyles];
1572
1577
  __decorateClass([
1573
1578
  property({ type: String, attribute: "agent-name" })
1574
- ], MulticornConsent.prototype, "agentName", 2);
1579
+ ], MulticornConsent.prototype, "agentName");
1575
1580
  __decorateClass([
1576
1581
  property({ type: String, attribute: "agent-color" })
1577
- ], MulticornConsent.prototype, "agentColor", 2);
1582
+ ], MulticornConsent.prototype, "agentColor");
1578
1583
  __decorateClass([
1579
1584
  property({ type: Array, attribute: "scopes" })
1580
- ], MulticornConsent.prototype, "scopes", 2);
1585
+ ], MulticornConsent.prototype, "scopes");
1581
1586
  __decorateClass([
1582
1587
  property({ type: Number, attribute: "spend-limit" })
1583
- ], MulticornConsent.prototype, "spendLimit", 2);
1588
+ ], MulticornConsent.prototype, "spendLimit");
1584
1589
  __decorateClass([
1585
1590
  property({ type: String })
1586
- ], MulticornConsent.prototype, "mode", 2);
1591
+ ], MulticornConsent.prototype, "mode");
1587
1592
  __decorateClass([
1588
1593
  state()
1589
- ], MulticornConsent.prototype, "_grantedScopes", 2);
1594
+ ], MulticornConsent.prototype, "_grantedScopes");
1590
1595
  __decorateClass([
1591
1596
  state()
1592
- ], MulticornConsent.prototype, "_adjustedSpendLimit", 2);
1597
+ ], MulticornConsent.prototype, "_adjustedSpendLimit");
1593
1598
  __decorateClass([
1594
1599
  state()
1595
- ], MulticornConsent.prototype, "_isOpen", 2);
1596
- MulticornConsent = __decorateClass([
1597
- customElement(CONSENT_ELEMENT_TAG)
1598
- ], MulticornConsent);
1600
+ ], MulticornConsent.prototype, "_isOpen");
1601
+ if (typeof customElements !== "undefined" && customElements.get(CONSENT_ELEMENT_TAG) === void 0) {
1602
+ customElements.define(CONSENT_ELEMENT_TAG, MulticornConsent);
1603
+ }
1604
+
1605
+ // src/badge/badge-styles.ts
1606
+ var LIGHT_TEXT = "#0f172a";
1607
+ var LIGHT_SURFACE = "#f8fafc";
1608
+ var LIGHT_SURFACE_HOVER = "#f1f5f9";
1609
+ var LIGHT_BORDER = "#e2e8f0";
1610
+ function getBadgeStyleText() {
1611
+ return `
1612
+ :host { display: inline-block; line-height: 0; }
1613
+ .badge {
1614
+ display: inline-flex;
1615
+ align-items: center;
1616
+ justify-content: center;
1617
+ box-sizing: border-box;
1618
+ gap: 6px;
1619
+ min-height: 28px;
1620
+ padding: 4px 10px 4px 8px;
1621
+ border-radius: 9999px;
1622
+ text-decoration: none;
1623
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
1624
+ font-size: 12px;
1625
+ font-weight: 500;
1626
+ border: 1px solid ${SHIELD_COLORS.border};
1627
+ background: ${SHIELD_COLORS.surface};
1628
+ color: ${SHIELD_COLORS.text};
1629
+ transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
1630
+ }
1631
+ :host([theme="light"]) .badge {
1632
+ border-color: ${LIGHT_BORDER};
1633
+ background: ${LIGHT_SURFACE};
1634
+ color: ${LIGHT_TEXT};
1635
+ }
1636
+ .badge:hover {
1637
+ background: ${SHIELD_COLORS.surfaceHover};
1638
+ border-color: ${SHIELD_COLORS.accent};
1639
+ box-shadow: 0 0 0 1px ${SHIELD_COLORS.accentDim};
1640
+ }
1641
+ :host([theme="light"]) .badge:hover {
1642
+ background: ${LIGHT_SURFACE_HOVER};
1643
+ border-color: ${SHIELD_COLORS.accent};
1644
+ }
1645
+ .badge:focus-visible {
1646
+ outline: 2px solid ${SHIELD_COLORS.accent};
1647
+ outline-offset: 2px;
1648
+ }
1649
+ .icon { flex-shrink: 0; display: block; }
1650
+ .text { white-space: nowrap; }
1651
+ :host([size="compact"]) .text { display: none; }
1652
+ :host([size="compact"]) .badge { padding: 4px 6px; }
1653
+ @media (prefers-reduced-motion: reduce) { .badge { transition: none; } }
1654
+ `.trim();
1655
+ }
1656
+
1657
+ // src/badge/multicorn-badge.ts
1658
+ var VERIFY_BASE = "https://multicorn.ai/verify/";
1659
+ var BADGE_ELEMENT_TAG = "multicorn-badge";
1660
+ var SHIELD_PATH = "M12 1L3 5v6c0 5.55 3.84 9.95 9 12 5.16-2.05 9-6.45 9-12V5l-9-4z";
1661
+ var SafeHTMLElement = typeof HTMLElement !== "undefined" ? HTMLElement : class {
1662
+ connectedCallback() {
1663
+ }
1664
+ };
1665
+ function parseOptionalCount(raw) {
1666
+ if (raw == null || raw === "") {
1667
+ return void 0;
1668
+ }
1669
+ const n = Number(raw);
1670
+ return Number.isNaN(n) ? void 0 : n;
1671
+ }
1672
+ var MulticornBadge = class extends SafeHTMLElement {
1673
+ #didInjectStyle = false;
1674
+ ensureShadow() {
1675
+ if (this.shadowRoot != null) {
1676
+ return this.shadowRoot;
1677
+ }
1678
+ return this.attachShadow({ mode: "open" });
1679
+ }
1680
+ static get observedAttributes() {
1681
+ return ["agent-id", "size", "theme", "action-count"];
1682
+ }
1683
+ connectedCallback() {
1684
+ this.render();
1685
+ }
1686
+ attributeChangedCallback() {
1687
+ this.render();
1688
+ }
1689
+ render() {
1690
+ const root = this.ensureShadow();
1691
+ if (this.#didInjectStyle) ; else {
1692
+ const style = document.createElement("style");
1693
+ style.textContent = getBadgeStyleText();
1694
+ root.appendChild(style);
1695
+ this.#didInjectStyle = true;
1696
+ }
1697
+ const agentId = (this.getAttribute("agent-id") ?? "").trim();
1698
+ const actionCount = parseOptionalCount(this.getAttribute("action-count"));
1699
+ const prior = root.querySelector("a.badge");
1700
+ if (prior) {
1701
+ prior.remove();
1702
+ }
1703
+ if (agentId === "") {
1704
+ return;
1705
+ }
1706
+ let labelSuffix;
1707
+ let ariaLabel;
1708
+ if (actionCount == null) {
1709
+ labelSuffix = "Secured by Multicorn";
1710
+ ariaLabel = "Secured by Multicorn, verify this agent";
1711
+ } else {
1712
+ const count = actionCount;
1713
+ const countText = String(count);
1714
+ labelSuffix = "Secured by Multicorn \xB7 " + countText + " actions secured";
1715
+ ariaLabel = "Secured by Multicorn \xB7 " + countText + " actions secured, verify this agent";
1716
+ }
1717
+ const href = `${VERIFY_BASE}${encodeURIComponent(agentId)}`;
1718
+ const a = document.createElement("a");
1719
+ a.className = "badge";
1720
+ a.href = href;
1721
+ a.target = "_blank";
1722
+ a.rel = "noopener noreferrer";
1723
+ a.setAttribute("aria-label", ariaLabel);
1724
+ const svgNs = "http://www.w3.org/2000/svg";
1725
+ const svg = document.createElementNS(svgNs, "svg");
1726
+ svg.setAttribute("class", "icon");
1727
+ svg.setAttribute("width", "16");
1728
+ svg.setAttribute("height", "16");
1729
+ svg.setAttribute("viewBox", "0 0 24 24");
1730
+ svg.setAttribute("aria-hidden", "true");
1731
+ const path = document.createElementNS(svgNs, "path");
1732
+ path.setAttribute("d", SHIELD_PATH);
1733
+ path.setAttribute("fill", SHIELD_COLORS.accent);
1734
+ svg.appendChild(path);
1735
+ a.appendChild(svg);
1736
+ const text = document.createElement("span");
1737
+ text.className = "text";
1738
+ text.textContent = labelSuffix;
1739
+ a.appendChild(text);
1740
+ root.appendChild(a);
1741
+ }
1742
+ };
1743
+ if (typeof customElements !== "undefined" && customElements.get(BADGE_ELEMENT_TAG) === void 0) {
1744
+ customElements.define(BADGE_ELEMENT_TAG, MulticornBadge);
1745
+ }
1599
1746
 
1600
1747
  // src/logger/action-logger.ts
1601
1748
  function createActionLogger(config) {
@@ -2743,4 +2890,4 @@ function validateApiKey(apiKey) {
2743
2890
  }
2744
2891
  }
2745
2892
 
2746
- export { ACTION_STATUSES, AGENT_STATUSES, BUILT_IN_SERVICES, CONSENT_ELEMENT_TAG, MulticornConsent, MulticornShield, PERMISSION_LEVELS, SERVICE_NAME_PATTERN, ScopeParseError, centsToDollars, createActionLogger, createFocusTrap, createMcpAdapter, createScopeRegistry, createSpendingChecker, dollarsToCents, formatScope, getPermissionLabel, getScopeLabel, getScopeShortLabel, getServiceDisplayName, getServiceIcon, hasScope, isBlockedResult, isPublicContentAction, isValidScopeString, parseScope, parseScopes, requestContentReview, requiresContentReview, tryParseScope, validateAllScopesAccess, validateScopeAccess };
2893
+ export { ACTION_STATUSES, AGENT_STATUSES, BUILT_IN_SERVICES, CONSENT_ELEMENT_TAG, MulticornBadge, MulticornConsent, MulticornShield, PERMISSION_LEVELS, SERVICE_NAME_PATTERN, ScopeParseError, centsToDollars, createActionLogger, createFocusTrap, createMcpAdapter, createScopeRegistry, createSpendingChecker, dollarsToCents, formatScope, getPermissionLabel, getScopeLabel, getScopeShortLabel, getServiceDisplayName, getServiceIcon, hasScope, isBlockedResult, isPublicContentAction, isValidScopeString, parseScope, parseScopes, requestContentReview, requiresContentReview, tryParseScope, validateAllScopesAccess, validateScopeAccess };