@clawdreyhepburn/carapace 0.3.2 → 0.4.1

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.
@@ -0,0 +1,143 @@
1
+ <svg width="100%" viewBox="0 0 680 530" xmlns="http://www.w3.org/2000/svg">
2
+ <defs>
3
+ <marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
4
+ <path d="M2 1L8 5L2 9" fill="none" stroke="context-stroke" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
5
+ </marker>
6
+
7
+ <mask id="imagine-text-gaps-jxkk9e" maskUnits="userSpaceOnUse"><rect x="0" y="0" width="680" height="530" fill="white"/><rect x="239.10523986816406" y="281.2499084472656" width="61.78950119018555" height="20.055686950683594" fill="black" rx="2"/><rect x="244" y="77.55548095703125" width="20.041765213012695" height="15.805651664733887" fill="black" rx="2"/><rect x="253.52288818359375" y="111.13880157470703" width="32.95419692993164" height="17.69455623626709" fill="black" rx="2"/><rect x="1.6765971183776855" y="8.388834953308105" width="20.646804809570312" height="12.027843475341797" fill="black" rx="2"/><rect x="425.48876953125" y="141.13880920410156" width="59.022552490234375" height="17.69455623626709" fill="black" rx="2"/><rect x="497.76171875" y="273.1387939453125" width="58.476539611816406" height="17.69455623626709" fill="black" rx="2"/><rect x="421.37786865234375" y="377.1387939453125" width="57.244327545166016" height="17.69455623626709" fill="black" rx="2"/><rect x="253.9434814453125" y="435.1387939453125" width="32.11304473876953" height="17.69455623626709" fill="black" rx="2"/><rect x="61.91438293457031" y="273.1387939453125" width="36.17123794555664" height="17.69455623626709" fill="black" rx="2"/><rect x="6" y="4.083252429962158" width="20.10817241668701" height="16.277877807617188" fill="black" rx="2"/><rect x="6" y="16.083251953125" width="41.69038009643555" height="16.277877807617188" fill="black" rx="2"/></mask></defs>
8
+
9
+ <!-- Dark background -->
10
+ <rect width="680" height="520" fill="#0a0a0a" style="fill:rgb(10, 10, 10);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
11
+
12
+ <!-- Subtle grid texture -->
13
+ <g opacity="0.04" stroke="#c4a87c" stroke-width="0.5" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.04;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto">
14
+ <line x1="0" y1="80" x2="680" y2="80" mask="url(#imagine-text-gaps-jxkk9e)" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
15
+ <line x1="0" y1="160" x2="680" y2="160" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
16
+ <line x1="0" y1="240" x2="680" y2="240" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
17
+ <line x1="0" y1="320" x2="680" y2="320" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
18
+ <line x1="0" y1="400" x2="680" y2="400" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
19
+ <line x1="0" y1="480" x2="680" y2="480" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
20
+ <line x1="80" y1="0" x2="80" y2="520" mask="url(#imagine-text-gaps-jxkk9e)" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
21
+ <line x1="160" y1="0" x2="160" y2="520" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
22
+ <line x1="240" y1="0" x2="240" y2="520" mask="url(#imagine-text-gaps-jxkk9e)" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
23
+ <line x1="320" y1="0" x2="320" y2="520" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
24
+ <line x1="400" y1="0" x2="400" y2="520" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
25
+ <line x1="480" y1="0" x2="480" y2="520" mask="url(#imagine-text-gaps-jxkk9e)" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
26
+ <line x1="560" y1="0" x2="560" y2="520" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
27
+ <line x1="640" y1="0" x2="640" y2="520" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
28
+ </g>
29
+
30
+ <!-- ====== AGENT CENTER ====== -->
31
+ <!-- Agent circle bg -->
32
+ <circle cx="270" cy="260" r="44" fill="#0f0d07" stroke="#c4a87c" stroke-width="1" opacity="0.9" style="fill:rgb(15, 13, 7);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.9;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
33
+ <!-- Robot head -->
34
+ <rect x="254" y="236" width="32" height="24" rx="4" style="fill:rgb(26, 21, 8);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:1.3px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
35
+ <!-- Robot eyes -->
36
+ <circle cx="263" cy="246" r="3" fill="#c4a87c" style="fill:rgb(196, 168, 124);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
37
+ <circle cx="277" cy="246" r="3" fill="#c4a87c" style="fill:rgb(196, 168, 124);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
38
+ <!-- Robot mouth -->
39
+ <rect x="261" y="253" width="14" height="3" rx="1" fill="#c4a87c" opacity="0.6" style="fill:rgb(196, 168, 124);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.6;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
40
+ <!-- Antenna -->
41
+ <line x1="270" y1="236" x2="270" y2="228" stroke="#c4a87c" stroke-width="1.2" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:1.2px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
42
+ <circle cx="270" cy="225" r="3" fill="#c4a87c" style="fill:rgb(196, 168, 124);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
43
+ <!-- Robot body -->
44
+ <rect x="256" y="262" width="28" height="18" rx="3" style="fill:rgb(26, 21, 8);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:1.3px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
45
+ <!-- Body slots -->
46
+ <rect x="260" y="266" width="7" height="3" rx="1" fill="#c4a87c" opacity="0.5" style="fill:rgb(196, 168, 124);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.5;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
47
+ <rect x="270" y="266" width="7" height="3" rx="1" fill="#c4a87c" opacity="0.5" style="fill:rgb(196, 168, 124);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.5;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
48
+ <!-- Agent label -->
49
+ <text x="270" y="296" text-anchor="middle" style="fill:rgb(196, 168, 124);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, sans-serif;font-size:13px;font-weight:500;text-anchor:middle;dominant-baseline:auto">AI Agent</text>
50
+
51
+ <!-- ====== ARROWS (all same style, radiating out) ====== -->
52
+ <!-- Top -->
53
+ <line x1="270" y1="216" x2="270" y2="112" marker-end="url(#arrow)" stroke="#c4a87c" mask="url(#imagine-text-gaps-jxkk9e)" style="fill:none;stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:1.2px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
54
+ <!-- Top-right (cloud API) -->
55
+ <line x1="301" y1="236" x2="450" y2="142" marker-end="url(#arrow)" stroke="#c4a87c" mask="url(#imagine-text-gaps-jxkk9e)" style="fill:none;stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:1.2px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
56
+ <!-- Right (payments) -->
57
+ <line x1="314" y1="260" x2="498" y2="260" marker-end="url(#arrow)" stroke="#c4a87c" style="fill:none;stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:1.2px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
58
+ <!-- Bottom-right (database) -->
59
+ <line x1="301" y1="284" x2="450" y2="375" marker-end="url(#arrow)" stroke="#c4a87c" style="fill:none;stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:1.2px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
60
+ <!-- Bottom (files) -->
61
+ <line x1="270" y1="304" x2="270" y2="400" marker-end="url(#arrow)" stroke="#c4a87c" style="fill:none;stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:1.2px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
62
+ <!-- Left (email) -->
63
+ <line x1="226" y1="260" x2="100" y2="260" marker-end="url(#arrow)" stroke="#c4a87c" style="fill:none;stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:1.2px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
64
+
65
+ <!-- ====== CAPABILITY ICONS ====== -->
66
+
67
+ <!-- TOP: Terminal / Shell -->
68
+ <rect x="240" y="72" width="60" height="40" rx="5" fill="#0f0d07" stroke="#c4a87c" stroke-width="0.8" opacity="0.9" style="fill:rgb(15, 13, 7);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.8px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.9;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
69
+ <text x="248" y="89" font-family="monospace" font-size="10" fill="#c4a87c" opacity="0.7" style="fill:rgb(196, 168, 124);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.7;font-family:monospace;font-size:10px;font-weight:400;text-anchor:start;dominant-baseline:auto">$_</text>
70
+ <line x1="247" y1="94" x2="291" y2="94" stroke="#c4a87c" stroke-width="0.6" opacity="0.3" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.6px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.3;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
71
+ <line x1="247" y1="99" x2="278" y2="99" stroke="#c4a87c" stroke-width="0.6" opacity="0.3" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.6px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.3;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
72
+ <text x="270" y="124" text-anchor="middle" style="fill:rgb(138, 130, 120);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, sans-serif;font-size:11px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Shell</text>
73
+
74
+ <!-- TOP-RIGHT: Cloud API -->
75
+ <!-- Cloud shape -->
76
+ <g transform="translate(430, 118)" style="fill:rgb(0, 0, 0);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto">
77
+ <path d="M8 22 Q3 22 2 17 Q-1 16 0 12 Q0 8 5 7 Q6 2 12 2 Q18 2 20 7 Q24 7 24 12 Q25 17 20 18 Q20 22 15 22 Z" fill="#0f0d07" stroke="#c4a87c" stroke-width="0.8" opacity="0.9" style="fill:rgb(15, 13, 7);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.8px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.9;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
78
+ <!-- API label inside cloud area -->
79
+ <text x="12" y="17" font-family="monospace" font-size="7" fill="#c4a87c" text-anchor="middle" opacity="0.8" style="fill:rgb(196, 168, 124);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.8;font-family:monospace;font-size:7px;font-weight:400;text-anchor:middle;dominant-baseline:auto">API</text>
80
+ </g>
81
+ <text x="455" y="154" text-anchor="middle" style="fill:rgb(138, 130, 120);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, sans-serif;font-size:11px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Cloud API</text>
82
+
83
+ <!-- RIGHT: Credit card / Payments -->
84
+ <g transform="translate(504, 240)" style="fill:rgb(0, 0, 0);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto">
85
+ <rect x="0" y="-14" width="42" height="28" rx="4" fill="#0f0d07" stroke="#c4a87c" stroke-width="0.8" opacity="0.9" style="fill:rgb(15, 13, 7);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.8px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.9;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
86
+ <line x1="0" y1="-6" x2="42" y2="-6" stroke="#c4a87c" stroke-width="1.5" opacity="0.6" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:1.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.6;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
87
+ <rect x="4" y="2" width="8" height="5" rx="1" fill="#c4a87c" opacity="0.4" style="fill:rgb(196, 168, 124);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.4;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
88
+ <rect x="15" y="3" width="16" height="2" rx="1" fill="#c4a87c" opacity="0.25" style="fill:rgb(196, 168, 124);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.25;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
89
+ <rect x="15" y="7" width="10" height="2" rx="1" fill="#c4a87c" opacity="0.2" style="fill:rgb(196, 168, 124);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.2;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
90
+ </g>
91
+ <text x="527" y="286" text-anchor="middle" style="fill:rgb(138, 130, 120);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, sans-serif;font-size:11px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Payments</text>
92
+
93
+ <!-- BOTTOM-RIGHT: Database -->
94
+ <g transform="translate(430, 360)" style="fill:rgb(0, 0, 0);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto">
95
+ <ellipse cx="14" cy="5" rx="14" ry="5" fill="#0f0d07" stroke="#c4a87c" stroke-width="0.8" opacity="0.9" style="fill:rgb(15, 13, 7);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.8px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.9;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
96
+ <path d="M0 5 Q0 14 14 14 Q28 14 28 5" fill="#0f0d07" stroke="#c4a87c" stroke-width="0.8" opacity="0.9" style="fill:rgb(15, 13, 7);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.8px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.9;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
97
+ <line x1="0" y1="9" x2="28" y2="9" stroke="#c4a87c" stroke-width="0.5" opacity="0.35" mask="url(#imagine-text-gaps-jxkk9e)" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.35;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
98
+ <ellipse cx="14" cy="9" rx="14" ry="3.5" fill="none" stroke="#c4a87c" stroke-width="0.5" opacity="0.25" style="fill:none;stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.25;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
99
+ </g>
100
+ <text x="450" y="390" text-anchor="middle" style="fill:rgb(138, 130, 120);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, sans-serif;font-size:11px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Database</text>
101
+
102
+ <!-- BOTTOM: File folder -->
103
+ <g transform="translate(247, 400)" style="fill:rgb(0, 0, 0);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto">
104
+ <path d="M0 8 Q0 0 8 0 L16 0 Q18 0 20 4 L42 4 Q46 4 46 8 L46 30 Q46 34 42 34 L4 34 Q0 34 0 30 Z" fill="#0f0d07" stroke="#c4a87c" stroke-width="0.8" opacity="0.9" style="fill:rgb(15, 13, 7);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.8px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.9;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
105
+ <line x1="4" y1="12" x2="42" y2="12" stroke="#c4a87c" stroke-width="0.5" opacity="0.3" mask="url(#imagine-text-gaps-jxkk9e)" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.5px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.3;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
106
+ <line x1="6" y1="18" x2="36" y2="18" stroke="#c4a87c" stroke-width="0.4" opacity="0.2" mask="url(#imagine-text-gaps-jxkk9e)" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.4px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.2;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
107
+ <line x1="6" y1="23" x2="30" y2="23" stroke="#c4a87c" stroke-width="0.4" opacity="0.2" mask="url(#imagine-text-gaps-jxkk9e)" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.4px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.2;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
108
+ </g>
109
+ <text x="270" y="448" text-anchor="middle" style="fill:rgb(138, 130, 120);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, sans-serif;font-size:11px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Files</text>
110
+
111
+ <!-- LEFT: Envelope / Email -->
112
+ <g transform="translate(58, 240)" style="fill:rgb(0, 0, 0);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto">
113
+ <rect x="0" y="-16" width="42" height="28" rx="3" fill="#0f0d07" stroke="#c4a87c" stroke-width="0.8" opacity="0.9" style="fill:rgb(15, 13, 7);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.8px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.9;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
114
+ <path d="M0 -16 L21 2 L42 -16" fill="none" stroke="#c4a87c" stroke-width="0.8" opacity="0.7" style="fill:none;stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.8px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.7;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
115
+ <line x1="0" y1="12" x2="14" y2="0" stroke="#c4a87c" stroke-width="0.6" opacity="0.3" mask="url(#imagine-text-gaps-jxkk9e)" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.6px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.3;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
116
+ <line x1="42" y1="12" x2="28" y2="0" stroke="#c4a87c" stroke-width="0.6" opacity="0.3" style="fill:rgb(0, 0, 0);stroke:rgb(196, 168, 124);color:rgb(0, 0, 0);stroke-width:0.6px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.3;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
117
+ </g>
118
+ <text x="80" y="286" text-anchor="middle" style="fill:rgb(138, 130, 120);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, sans-serif;font-size:11px;font-weight:400;text-anchor:middle;dominant-baseline:auto">Email</text>
119
+
120
+ <!-- ====== POST-IT NOTE (slightly askew, near agent) ====== -->
121
+ <g transform="translate(164, 155) rotate(-6)" style="fill:rgb(0, 0, 0);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto">
122
+ <!-- Drop shadow suggestion -->
123
+ <rect x="3" y="3" width="72" height="44" rx="2" fill="#000" opacity="0.35" style="fill:rgb(0, 0, 0);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.35;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
124
+ <!-- Post-it body -->
125
+ <rect x="0" y="0" width="72" height="44" rx="2" fill="#f5e642" style="fill:rgb(245, 230, 66);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
126
+ <!-- Tape strip at top -->
127
+ <rect x="22" y="-5" width="28" height="8" rx="2" fill="#d4c520" opacity="0.55" style="fill:rgb(212, 197, 32);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.55;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
128
+ <!-- Text lines -->
129
+ <text x="10" y="16" style="fill:rgb(42, 34, 24);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, sans-serif;font-size:10px;font-weight:500;text-anchor:start;dominant-baseline:auto">be</text>
130
+ <text x="10" y="28" style="fill:rgb(42, 34, 24);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:1;font-family:&quot;Anthropic Sans&quot;, sans-serif;font-size:10px;font-weight:500;text-anchor:start;dominant-baseline:auto">careful</text>
131
+ <!-- Small doodle scribble -->
132
+ <path d="M10 36 Q30 34 50 37" fill="none" stroke="#2a2218" stroke-width="0.7" opacity="0.3" style="fill:none;stroke:rgb(42, 34, 24);color:rgb(0, 0, 0);stroke-width:0.7px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.3;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
133
+ </g>
134
+
135
+ <!-- Open "threat" glow dots on arrows to reinforce "everything is exposed" -->
136
+ <circle cx="270" cy="164" r="2.5" fill="#c4a87c" opacity="0.35" style="fill:rgb(196, 168, 124);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.35;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
137
+ <circle cx="375" cy="189" r="2.5" fill="#c4a87c" opacity="0.35" style="fill:rgb(196, 168, 124);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.35;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
138
+ <circle cx="406" cy="260" r="2.5" fill="#c4a87c" opacity="0.35" style="fill:rgb(196, 168, 124);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.35;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
139
+ <circle cx="375" cy="329" r="2.5" fill="#c4a87c" opacity="0.35" style="fill:rgb(196, 168, 124);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.35;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
140
+ <circle cx="270" cy="352" r="2.5" fill="#c4a87c" opacity="0.35" style="fill:rgb(196, 168, 124);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.35;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
141
+ <circle cx="163" cy="260" r="2.5" fill="#c4a87c" opacity="0.35" style="fill:rgb(196, 168, 124);stroke:none;color:rgb(0, 0, 0);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;opacity:0.35;font-family:&quot;Anthropic Sans&quot;, -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
142
+
143
+ </svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdreyhepburn/carapace",
3
- "version": "0.3.2",
3
+ "version": "0.4.1",
4
4
  "description": "Immutable policy boundaries for MCP tool access. Powered by Cedar + Cedarling WASM.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -150,14 +150,18 @@ export class CedarlingEngine {
150
150
  const typeMatch = request.resource.match(/^(?:\w+::)?(\w+)::/);
151
151
  if (typeMatch) resourceEntityType = typeMatch[1];
152
152
 
153
+ const cedarContext: Record<string, unknown> = { ...(request.context ?? {}) };
154
+
155
+ const effectivePrincipalId = principalId;
156
+
153
157
  const result = await this.cedarling.authorize_unsigned({
154
158
  principals: [
155
159
  {
156
160
  cedar_entity_mapping: {
157
161
  entity_type: `${this.namespace}::${this.agentEntityType}`,
158
- id: principalId,
162
+ id: effectivePrincipalId,
159
163
  },
160
- name: principalId,
164
+ name: effectivePrincipalId,
161
165
  },
162
166
  ],
163
167
  action: `${this.namespace}::Action::"${actionName}"`,
@@ -168,7 +172,7 @@ export class CedarlingEngine {
168
172
  },
169
173
  ...(request.context ?? {}),
170
174
  },
171
- context: request.context ?? {},
175
+ context: cedarContext,
172
176
  });
173
177
 
174
178
  const decision = result.decision ? "allow" : "deny";
@@ -496,6 +500,38 @@ export class CedarlingEngine {
496
500
  },
497
501
  },
498
502
  },
503
+ Agent: {
504
+ shape: {
505
+ type: "Record",
506
+ attributes: {
507
+ role: {
508
+ type: "EntityOrCommon",
509
+ name: "String",
510
+ required: false,
511
+ },
512
+ parentChain: {
513
+ type: "Set",
514
+ element: { type: "EntityOrCommon", name: "String" },
515
+ required: false,
516
+ },
517
+ issuer: {
518
+ type: "EntityOrCommon",
519
+ name: "String",
520
+ required: false,
521
+ },
522
+ depth: {
523
+ type: "EntityOrCommon",
524
+ name: "Long",
525
+ required: false,
526
+ },
527
+ attestation_proven: {
528
+ type: "EntityOrCommon",
529
+ name: "Boolean",
530
+ required: false,
531
+ },
532
+ },
533
+ },
534
+ },
499
535
  Tool: {
500
536
  shape: {
501
537
  type: "Record",
@@ -510,6 +546,21 @@ export class CedarlingEngine {
510
546
  name: "String",
511
547
  required: false,
512
548
  },
549
+ project: {
550
+ type: "EntityOrCommon",
551
+ name: "String",
552
+ required: false,
553
+ },
554
+ team: {
555
+ type: "EntityOrCommon",
556
+ name: "String",
557
+ required: false,
558
+ },
559
+ domain: {
560
+ type: "EntityOrCommon",
561
+ name: "String",
562
+ required: false,
563
+ },
513
564
  },
514
565
  },
515
566
  },
@@ -556,9 +607,17 @@ export class CedarlingEngine {
556
607
  actions: {
557
608
  call_tool: {
558
609
  appliesTo: {
559
- principalTypes: [this.agentEntityType],
610
+ principalTypes: [this.agentEntityType, "Agent"],
560
611
  resourceTypes: ["Tool"],
561
- context: { type: "Record", attributes: {} },
612
+ context: {
613
+ type: "Record",
614
+ attributes: {
615
+ agent_role: { type: "EntityOrCommon", name: "String", required: false },
616
+ agent_issuer: { type: "EntityOrCommon", name: "String", required: false },
617
+ agent_depth: { type: "EntityOrCommon", name: "Long", required: false },
618
+ agent_attestation_proven: { type: "EntityOrCommon", name: "Boolean", required: false },
619
+ },
620
+ },
562
621
  },
563
622
  },
564
623
  list_tools: {
package/src/gui/server.ts CHANGED
@@ -24,11 +24,13 @@ export class ControlGui {
24
24
  private logger: Logger;
25
25
  private server: Server | null = null;
26
26
 
27
+
27
28
  constructor(opts: GuiOpts) {
28
29
  this.port = opts.port;
29
30
  this.aggregator = opts.aggregator;
30
31
  this.cedar = opts.cedar;
31
32
  this.logger = opts.logger;
33
+
32
34
  }
33
35
 
34
36
  async start(): Promise<void> {
@@ -134,6 +136,21 @@ export class ControlGui {
134
136
  return;
135
137
  }
136
138
 
139
+ if (url.pathname === "/api/agents" && req.method === "GET") {
140
+ // Agent hierarchy removed — see @clawdreyhepburn/ovid-me for per-agent mandates
141
+ this.json(res, []);
142
+ return;
143
+ }
144
+
145
+ if (url.pathname === "/api/policy-source" && req.method === "GET") {
146
+ // Return all Cedar policies (deployment-wide ceiling)
147
+ const policies = this.cedar.getPolicies();
148
+ const policyText = policies.map(p => p.raw).join("\n\n");
149
+ res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
150
+ res.end(policyText || "# No policies defined\n");
151
+ return;
152
+ }
153
+
137
154
  // --- GUI ---
138
155
  if (url.pathname === "/" || url.pathname === "/index.html") {
139
156
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
package/src/index.ts CHANGED
@@ -11,6 +11,8 @@ import { ControlGui } from "./gui/server.js";
11
11
  import { LlmProxy } from "./llm-proxy.js";
12
12
  import type { PluginConfig } from "./types.js";
13
13
 
14
+ export { CarapacePolicySource } from "./policy-source.js";
15
+ export type { PolicySource } from "./policy-source.js";
14
16
  export const id = "carapace";
15
17
  export const name = "Carapace";
16
18
 
package/src/llm-proxy.ts CHANGED
@@ -63,6 +63,14 @@ export class LlmProxy {
63
63
  toolCallsDenied: 0,
64
64
  };
65
65
 
66
+ // Audit log for GUI display
67
+ private auditLog: Array<{
68
+ timestamp: number;
69
+ tool: string;
70
+ decision: "allow" | "deny";
71
+ reasons: string[];
72
+ }> = [];
73
+
66
74
  constructor(opts: LlmProxyOpts) {
67
75
  this.port = opts.port;
68
76
  this.upstream = opts.upstream;
@@ -70,6 +78,10 @@ export class LlmProxy {
70
78
  this.logger = opts.logger;
71
79
  }
72
80
 
81
+ getAuditLog() {
82
+ return this.auditLog.slice(-100); // last 100 entries
83
+ }
84
+
73
85
  async start(): Promise<void> {
74
86
  this.server = createServer(async (req, res) => {
75
87
  try {
@@ -596,6 +608,15 @@ export class LlmProxy {
596
608
  context,
597
609
  });
598
610
 
611
+ // Audit log entry
612
+ this.auditLog.push({
613
+ timestamp: Date.now(),
614
+ tool: toolName,
615
+ decision: decision.decision,
616
+ reasons: decision.reasons,
617
+ });
618
+ if (this.auditLog.length > 500) this.auditLog.splice(0, this.auditLog.length - 100);
619
+
599
620
  if (decision.decision === "deny") {
600
621
  this.stats.toolCallsDenied++;
601
622
  }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * PolicySource — exposes Carapace's deployment-level Cedar policies
3
+ * so that OVID-ME can query the effective policy ceiling.
4
+ */
5
+
6
+ import { readFileSync, readdirSync, existsSync } from "node:fs";
7
+ import { join } from "node:path";
8
+ import { homedir } from "node:os";
9
+
10
+ /**
11
+ * Must match @clawdreyhepburn/ovid-me PolicySource interface.
12
+ *
13
+ * Kept as a local copy because ovid-me pulls in native dependencies
14
+ * (better-sqlite3) that would bloat Carapace's install. A type
15
+ * compatibility test in test/policy-source.test.ts guards against drift.
16
+ *
17
+ * Canonical definition: ovid-me/src/config.ts
18
+ */
19
+ export interface PolicySource {
20
+ getEffectivePolicy(principal: string): Promise<string | null>;
21
+ }
22
+
23
+ /**
24
+ * Reads all .cedar files from the policy directory and returns
25
+ * the concatenated policy text. Carapace policies are deployment-wide
26
+ * (not per-principal), so all policies apply to all principals.
27
+ */
28
+ export class CarapacePolicySource implements PolicySource {
29
+ private policyDir: string;
30
+
31
+ constructor(policyDir?: string) {
32
+ this.policyDir = (policyDir ?? "~/.openclaw/mcp-policies/").replace("~", homedir());
33
+ }
34
+
35
+ async getEffectivePolicy(_principal: string): Promise<string | null> {
36
+ if (!existsSync(this.policyDir)) return null;
37
+
38
+ const files = readdirSync(this.policyDir).filter(f => f.endsWith(".cedar"));
39
+ if (files.length === 0) return null;
40
+
41
+ const policies = files.map(f => readFileSync(join(this.policyDir, f), "utf-8"));
42
+ return policies.join("\n\n");
43
+ }
44
+ }
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ include: ['test/**/*.test.{js,mjs,ts}'],
6
+ testTimeout: 60000,
7
+ },
8
+ });