@clawdreyhepburn/carapace 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/README.md +36 -1
- package/dist/cedar-engine-cedarling.d.ts +81 -0
- package/dist/cedar-engine-cedarling.js +651 -0
- package/dist/cedar-engine-cedarling.js.map +1 -0
- package/dist/cedar-engine.d.ts +77 -0
- package/dist/cedar-engine.js +374 -0
- package/dist/cedar-engine.js.map +1 -0
- package/dist/gui/html.d.ts +5 -0
- package/dist/gui/html.js +930 -0
- package/dist/gui/html.js.map +1 -0
- package/dist/gui/server.d.ts +28 -0
- package/dist/gui/server.js +159 -0
- package/dist/gui/server.js.map +1 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.js +584 -0
- package/dist/index.js.map +1 -0
- package/dist/llm-proxy.d.ts +75 -0
- package/dist/llm-proxy.js +565 -0
- package/dist/llm-proxy.js.map +1 -0
- package/dist/mcp-aggregator.d.ts +29 -0
- package/dist/mcp-aggregator.js +144 -0
- package/dist/mcp-aggregator.js.map +1 -0
- package/dist/policy-source.d.ts +21 -0
- package/dist/policy-source.js +28 -0
- package/dist/policy-source.js.map +1 -0
- package/dist/types.d.ts +135 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/docs/carapace_proxy_tool_filter_flow_v3.svg +96 -0
- package/docs/ungated_ai_agent_capabilities.svg +143 -0
- package/package.json +1 -1
- package/src/cedar-engine-cedarling.ts +68 -5
- package/src/cedar-engine.ts +4 -0
- package/src/gui/html.ts +14 -3
- package/src/gui/server.ts +18 -0
- package/src/index.ts +2 -0
- package/src/llm-proxy.ts +21 -0
- package/src/policy-source.ts +39 -0
- package/src/types.ts +1 -0
- package/vitest.config.ts +8 -0
|
@@ -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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", 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:"Anthropic Sans", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", 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:"Anthropic Sans", -apple-system, "system-ui", "Segoe UI", sans-serif;font-size:16px;font-weight:400;text-anchor:start;dominant-baseline:auto"/>
|
|
142
|
+
|
|
143
|
+
</svg>
|
package/package.json
CHANGED
|
@@ -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:
|
|
162
|
+
id: effectivePrincipalId,
|
|
159
163
|
},
|
|
160
|
-
name:
|
|
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:
|
|
175
|
+
context: cedarContext,
|
|
172
176
|
});
|
|
173
177
|
|
|
174
178
|
const decision = result.decision ? "allow" : "deny";
|
|
@@ -276,6 +280,10 @@ export class CedarlingEngine {
|
|
|
276
280
|
return true;
|
|
277
281
|
}
|
|
278
282
|
|
|
283
|
+
getDefaultPolicy(): "deny-all" | "allow-all" {
|
|
284
|
+
return this.defaultPolicy;
|
|
285
|
+
}
|
|
286
|
+
|
|
279
287
|
getPolicies(): Array<{ id: string; effect: string; raw: string }> {
|
|
280
288
|
return [...this.policies.entries()].map(([id, p]) => ({ id, ...p }));
|
|
281
289
|
}
|
|
@@ -492,6 +500,38 @@ export class CedarlingEngine {
|
|
|
492
500
|
},
|
|
493
501
|
},
|
|
494
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
|
+
},
|
|
495
535
|
Tool: {
|
|
496
536
|
shape: {
|
|
497
537
|
type: "Record",
|
|
@@ -506,6 +546,21 @@ export class CedarlingEngine {
|
|
|
506
546
|
name: "String",
|
|
507
547
|
required: false,
|
|
508
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
|
+
},
|
|
509
564
|
},
|
|
510
565
|
},
|
|
511
566
|
},
|
|
@@ -552,9 +607,17 @@ export class CedarlingEngine {
|
|
|
552
607
|
actions: {
|
|
553
608
|
call_tool: {
|
|
554
609
|
appliesTo: {
|
|
555
|
-
principalTypes: [this.agentEntityType],
|
|
610
|
+
principalTypes: [this.agentEntityType, "Agent"],
|
|
556
611
|
resourceTypes: ["Tool"],
|
|
557
|
-
context: {
|
|
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
|
+
},
|
|
558
621
|
},
|
|
559
622
|
},
|
|
560
623
|
list_tools: {
|
package/src/cedar-engine.ts
CHANGED
|
@@ -218,6 +218,10 @@ export class CedarEngine {
|
|
|
218
218
|
}
|
|
219
219
|
|
|
220
220
|
/** Get all policies as raw text */
|
|
221
|
+
getDefaultPolicy(): "deny-all" | "allow-all" {
|
|
222
|
+
return this.defaultPolicy;
|
|
223
|
+
}
|
|
224
|
+
|
|
221
225
|
getPolicies(): Array<{ id: string; effect: string; raw: string }> {
|
|
222
226
|
return [...this.policies.values()].map((p) => ({
|
|
223
227
|
id: p.id,
|
package/src/gui/html.ts
CHANGED
|
@@ -341,7 +341,7 @@ export function guiHtml(): string {
|
|
|
341
341
|
|
|
342
342
|
<div class="container">
|
|
343
343
|
<div id="servers-section">
|
|
344
|
-
<h2>Servers</h2>
|
|
344
|
+
<h2>MCP Servers</h2>
|
|
345
345
|
<div class="servers" id="servers"></div>
|
|
346
346
|
</div>
|
|
347
347
|
|
|
@@ -540,8 +540,18 @@ export function guiHtml(): string {
|
|
|
540
540
|
}
|
|
541
541
|
|
|
542
542
|
function renderServers() {
|
|
543
|
+
const section = document.getElementById('servers-section');
|
|
543
544
|
const el = document.getElementById('servers');
|
|
544
545
|
const serverFilter = document.getElementById('server-filter');
|
|
546
|
+
const serverNames = Object.keys(state.servers);
|
|
547
|
+
|
|
548
|
+
// Hide entire section when no MCP servers are configured
|
|
549
|
+
if (serverNames.length === 0) {
|
|
550
|
+
section.style.display = 'none';
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
section.style.display = '';
|
|
554
|
+
|
|
545
555
|
el.innerHTML = Object.entries(state.servers).map(([name, s]) =>
|
|
546
556
|
'<div class="server-card"><div class="name">' +
|
|
547
557
|
'<span class="dot ' + (s.connected ? 'connected' : 'disconnected') + '"></span>' +
|
|
@@ -552,7 +562,7 @@ export function guiHtml(): string {
|
|
|
552
562
|
// Update server filter dropdown (preserve selection)
|
|
553
563
|
const prev = serverFilter.value;
|
|
554
564
|
serverFilter.innerHTML = '<option value="all">All servers</option>' +
|
|
555
|
-
|
|
565
|
+
serverNames.map(n => '<option value="' + esc(n) + '">' + esc(n) + '</option>').join('');
|
|
556
566
|
serverFilter.value = prev || 'all';
|
|
557
567
|
}
|
|
558
568
|
|
|
@@ -665,7 +675,8 @@ export function guiHtml(): string {
|
|
|
665
675
|
const el = document.getElementById('policies-list');
|
|
666
676
|
const policies = state.policies ?? [];
|
|
667
677
|
if (policies.length === 0) {
|
|
668
|
-
|
|
678
|
+
const mode = state.defaultPolicy === 'deny-all' ? 'Default deny is active — all tools are blocked.' : 'Default allow is active — all tools are permitted.';
|
|
679
|
+
el.innerHTML = '<div class="empty-state">No policies loaded. ' + mode + '<br><br>' +
|
|
669
680
|
'<button class="primary" onclick="openBuilder()">+ Create your first policy</button></div>';
|
|
670
681
|
return;
|
|
671
682
|
}
|
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> {
|
|
@@ -66,6 +68,7 @@ export class ControlGui {
|
|
|
66
68
|
policies: this.cedar.getPolicies(),
|
|
67
69
|
toolCount: tools.length,
|
|
68
70
|
enabledCount: tools.filter((t) => t.enabled).length,
|
|
71
|
+
defaultPolicy: this.cedar.getDefaultPolicy?.() ?? "allow-all",
|
|
69
72
|
});
|
|
70
73
|
return;
|
|
71
74
|
}
|
|
@@ -133,6 +136,21 @@ export class ControlGui {
|
|
|
133
136
|
return;
|
|
134
137
|
}
|
|
135
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
|
+
|
|
136
154
|
// --- GUI ---
|
|
137
155
|
if (url.pathname === "/" || url.pathname === "/index.html") {
|
|
138
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,39 @@
|
|
|
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
|
+
* Interface matching @clawdreyhepburn/ovid-me's PolicySource.
|
|
12
|
+
* Defined locally to avoid circular dependencies.
|
|
13
|
+
*/
|
|
14
|
+
export interface PolicySource {
|
|
15
|
+
getEffectivePolicy(principal: string): Promise<string | null>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Reads all .cedar files from the policy directory and returns
|
|
20
|
+
* the concatenated policy text. Carapace policies are deployment-wide
|
|
21
|
+
* (not per-principal), so all policies apply to all principals.
|
|
22
|
+
*/
|
|
23
|
+
export class CarapacePolicySource implements PolicySource {
|
|
24
|
+
private policyDir: string;
|
|
25
|
+
|
|
26
|
+
constructor(policyDir?: string) {
|
|
27
|
+
this.policyDir = (policyDir ?? "~/.openclaw/mcp-policies/").replace("~", homedir());
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async getEffectivePolicy(_principal: string): Promise<string | null> {
|
|
31
|
+
if (!existsSync(this.policyDir)) return null;
|
|
32
|
+
|
|
33
|
+
const files = readdirSync(this.policyDir).filter(f => f.endsWith(".cedar"));
|
|
34
|
+
if (files.length === 0) return null;
|
|
35
|
+
|
|
36
|
+
const policies = files.map(f => readFileSync(join(this.policyDir, f), "utf-8"));
|
|
37
|
+
return policies.join("\n\n");
|
|
38
|
+
}
|
|
39
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -105,6 +105,7 @@ export interface CedarEngineInterface {
|
|
|
105
105
|
isToolEnabled(qualifiedName: string): boolean;
|
|
106
106
|
savePolicy(id: string, raw: string): void;
|
|
107
107
|
deletePolicy(id: string): boolean;
|
|
108
|
+
getDefaultPolicy(): "deny-all" | "allow-all";
|
|
108
109
|
getPolicies(): Array<{ id: string; effect: string; raw: string }>;
|
|
109
110
|
getSchema(): CedarSchemaInfo;
|
|
110
111
|
saveSchema(raw: string): void;
|