@n2world/orchestrator 1.1.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.
Files changed (154) hide show
  1. package/dist/agent-os-rd.d.ts +100 -0
  2. package/dist/agent-os-rd.js +258 -0
  3. package/dist/audit-store.d.ts +14 -0
  4. package/dist/audit-store.js +107 -0
  5. package/dist/beta-runner.d.ts +95 -0
  6. package/dist/beta-runner.js +251 -0
  7. package/dist/beta.d.ts +102 -0
  8. package/dist/beta.js +180 -0
  9. package/dist/browser-agent.d.ts +90 -0
  10. package/dist/browser-agent.js +223 -0
  11. package/dist/channel-gateway.d.ts +74 -0
  12. package/dist/channel-gateway.js +270 -0
  13. package/dist/channels.d.ts +120 -0
  14. package/dist/channels.js +432 -0
  15. package/dist/chat-store.d.ts +29 -0
  16. package/dist/chat-store.js +120 -0
  17. package/dist/cli.d.ts +2 -0
  18. package/dist/cli.js +607 -0
  19. package/dist/command-screen.d.ts +12 -0
  20. package/dist/command-screen.js +44 -0
  21. package/dist/commit-gate.d.ts +98 -0
  22. package/dist/commit-gate.js +258 -0
  23. package/dist/companion-api.d.ts +37 -0
  24. package/dist/companion-api.js +101 -0
  25. package/dist/conversation-graph.d.ts +39 -0
  26. package/dist/conversation-graph.js +92 -0
  27. package/dist/cost-estimator.d.ts +27 -0
  28. package/dist/cost-estimator.js +42 -0
  29. package/dist/cron-runner.d.ts +31 -0
  30. package/dist/cron-runner.js +46 -0
  31. package/dist/dashboard/chat.html +326 -0
  32. package/dist/dashboard/dental.html +58 -0
  33. package/dist/dashboard/freebie.png +0 -0
  34. package/dist/dashboard/icon-192.png +0 -0
  35. package/dist/dashboard/index.html +892 -0
  36. package/dist/dashboard/manifest.json +15 -0
  37. package/dist/dashboard/service-worker.js +28 -0
  38. package/dist/dashboard-server.d.ts +37 -0
  39. package/dist/dashboard-server.js +457 -0
  40. package/dist/dental-intake-service.d.ts +37 -0
  41. package/dist/dental-intake-service.js +61 -0
  42. package/dist/dental-metrics.d.ts +25 -0
  43. package/dist/dental-metrics.js +37 -0
  44. package/dist/docking.d.ts +36 -0
  45. package/dist/docking.js +73 -0
  46. package/dist/finance-mcts-candidate.d.ts +37 -0
  47. package/dist/finance-mcts-candidate.js +106 -0
  48. package/dist/finance-regulation-kr.d.ts +33 -0
  49. package/dist/finance-regulation-kr.js +104 -0
  50. package/dist/finance-workflow.d.ts +135 -0
  51. package/dist/finance-workflow.js +242 -0
  52. package/dist/gateway.d.ts +18 -0
  53. package/dist/gateway.js +123 -0
  54. package/dist/governance.d.ts +39 -0
  55. package/dist/governance.js +48 -0
  56. package/dist/governed-executor.d.ts +31 -0
  57. package/dist/governed-executor.js +63 -0
  58. package/dist/governed-llm.d.ts +41 -0
  59. package/dist/governed-llm.js +83 -0
  60. package/dist/gpu-bridge.d.ts +16 -0
  61. package/dist/gpu-bridge.js +53 -0
  62. package/dist/health.d.ts +47 -0
  63. package/dist/health.js +66 -0
  64. package/dist/identity-link.d.ts +32 -0
  65. package/dist/identity-link.js +98 -0
  66. package/dist/index.d.ts +184 -0
  67. package/dist/index.js +417 -0
  68. package/dist/integrations/emr-adapter.d.ts +41 -0
  69. package/dist/integrations/emr-adapter.js +63 -0
  70. package/dist/kakao-oauth.d.ts +16 -0
  71. package/dist/kakao-oauth.js +87 -0
  72. package/dist/knowledge-graph.d.ts +53 -0
  73. package/dist/knowledge-graph.js +156 -0
  74. package/dist/llm.d.ts +65 -0
  75. package/dist/llm.js +357 -0
  76. package/dist/mcp-client-guard.d.ts +32 -0
  77. package/dist/mcp-client-guard.js +179 -0
  78. package/dist/mcp-macaroon.d.ts +75 -0
  79. package/dist/mcp-macaroon.js +161 -0
  80. package/dist/mcts-kernel-bridge.d.ts +36 -0
  81. package/dist/mcts-kernel-bridge.js +99 -0
  82. package/dist/mcts-prior.d.ts +79 -0
  83. package/dist/mcts-prior.js +170 -0
  84. package/dist/model-router.d.ts +51 -0
  85. package/dist/model-router.js +75 -0
  86. package/dist/multi-axis-lift.d.ts +43 -0
  87. package/dist/multi-axis-lift.js +141 -0
  88. package/dist/net-guard.d.ts +39 -0
  89. package/dist/net-guard.js +141 -0
  90. package/dist/onboarding.d.ts +38 -0
  91. package/dist/onboarding.js +94 -0
  92. package/dist/oracle-anchored-search.d.ts +25 -0
  93. package/dist/oracle-anchored-search.js +50 -0
  94. package/dist/oracle.d.ts +22 -0
  95. package/dist/oracle.js +116 -0
  96. package/dist/p6-governance.d.ts +150 -0
  97. package/dist/p6-governance.js +252 -0
  98. package/dist/pairing.d.ts +22 -0
  99. package/dist/pairing.js +81 -0
  100. package/dist/personalization.d.ts +35 -0
  101. package/dist/personalization.js +73 -0
  102. package/dist/pglite-hnsw-bridge.d.ts +118 -0
  103. package/dist/pglite-hnsw-bridge.js +311 -0
  104. package/dist/pglite-store.d.ts +59 -0
  105. package/dist/pglite-store.js +180 -0
  106. package/dist/playbook.d.ts +79 -0
  107. package/dist/playbook.js +83 -0
  108. package/dist/playbooks/dental-intake.d.ts +20 -0
  109. package/dist/playbooks/dental-intake.js +112 -0
  110. package/dist/predictive-agent.d.ts +157 -0
  111. package/dist/predictive-agent.js +535 -0
  112. package/dist/prompt-optimizer.d.ts +18 -0
  113. package/dist/prompt-optimizer.js +104 -0
  114. package/dist/rate-limiter.d.ts +25 -0
  115. package/dist/rate-limiter.js +75 -0
  116. package/dist/safety-anneal.d.ts +83 -0
  117. package/dist/safety-anneal.js +153 -0
  118. package/dist/sandbox-controller.d.ts +12 -0
  119. package/dist/sandbox-controller.js +95 -0
  120. package/dist/satisfaction-metrics.d.ts +26 -0
  121. package/dist/satisfaction-metrics.js +61 -0
  122. package/dist/sensor-bridge.d.ts +53 -0
  123. package/dist/sensor-bridge.js +133 -0
  124. package/dist/session-repair.d.ts +27 -0
  125. package/dist/session-repair.js +66 -0
  126. package/dist/slack-finance-intake.d.ts +42 -0
  127. package/dist/slack-finance-intake.js +122 -0
  128. package/dist/symbolic-dynamics.d.ts +113 -0
  129. package/dist/symbolic-dynamics.js +420 -0
  130. package/dist/telemetry.d.ts +19 -0
  131. package/dist/telemetry.js +68 -0
  132. package/dist/text-embedding.d.ts +6 -0
  133. package/dist/text-embedding.js +42 -0
  134. package/dist/tier-classifier.d.ts +20 -0
  135. package/dist/tier-classifier.js +58 -0
  136. package/dist/tier-guard.d.ts +36 -0
  137. package/dist/tier-guard.js +56 -0
  138. package/dist/tui.d.ts +9 -0
  139. package/dist/tui.js +214 -0
  140. package/dist/update-security.d.ts +31 -0
  141. package/dist/update-security.js +112 -0
  142. package/dist/v-calibration.d.ts +16 -0
  143. package/dist/v-calibration.js +42 -0
  144. package/dist/value-calibration.d.ts +41 -0
  145. package/dist/value-calibration.js +133 -0
  146. package/dist/value-head.d.ts +20 -0
  147. package/dist/value-head.js +91 -0
  148. package/dist/wal-buffer.d.ts +23 -0
  149. package/dist/wal-buffer.js +144 -0
  150. package/dist/wiki-synthesizer.d.ts +80 -0
  151. package/dist/wiki-synthesizer.js +0 -0
  152. package/dist/worker-agent.d.ts +10 -0
  153. package/dist/worker-agent.js +19 -0
  154. package/package.json +65 -0
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ // ============================================================================
3
+ // v2.5.2 Phase 6 — MCP 클라이언트 가드 + A2UI 격리 헬퍼
4
+ // ----------------------------------------------------------------------------
5
+ // 계획서 v2.5.2 §3.4/§보안: 외부 MCP 도구는 신뢰 불가 — 허용목록·SSRF 가드·출력
6
+ // 스키마 검증·프롬프트 인젝션 필터. A2UI는 sandboxed iframe + 엄격 CSP + provenance.
7
+ // (Macaroon=권한 위임, 본 모듈=오염 차단 — 분리 적용.)
8
+ //
9
+ // 정직 고지(제1계명): 본 모듈은 *정책/검증 로직*이며 테스트로 검증된다. 실제 브라우저
10
+ // 렌더링(iframe/CSP 강제)은 런타임에서 본 헬퍼가 생성한 정책을 적용해야 효력이 있다.
11
+ // ============================================================================
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.A2UI_SANDBOX = void 0;
47
+ exports.isSafeMcpUrl = isSafeMcpUrl;
48
+ exports.isPrivateIp = isPrivateIp;
49
+ exports.isSafeResolvedUrl = isSafeResolvedUrl;
50
+ exports.sanitizeToolOutput = sanitizeToolOutput;
51
+ exports.a2uiCsp = a2uiCsp;
52
+ exports.provenanceBanner = provenanceBanner;
53
+ // ── MCP 서버 허용목록 + SSRF 가드 ───────────────────────────────────────────
54
+ const dns_1 = require("dns");
55
+ const net = __importStar(require("net"));
56
+ const PRIVATE_HOST = /^(localhost|127\.|0\.0\.0\.0|10\.|192\.168\.|172\.(1[6-9]|2\d|3[01])\.|169\.254\.|\[?::1\]?|\[?fe80:)/i;
57
+ const METADATA_HOST = /(169\.254\.169\.254|metadata\.google\.internal|metadata\.azure)/i;
58
+ function isSafeMcpUrl(url, allowHosts) {
59
+ let u;
60
+ try {
61
+ u = new URL(url);
62
+ }
63
+ catch {
64
+ return { ok: false, reason: 'URL 파싱 실패' };
65
+ }
66
+ if (u.protocol !== 'https:')
67
+ return { ok: false, reason: 'https 아님(평문 차단)' };
68
+ if (PRIVATE_HOST.test(u.hostname))
69
+ return { ok: false, reason: `사설/루프백 호스트 차단(${u.hostname})` };
70
+ if (METADATA_HOST.test(u.hostname))
71
+ return { ok: false, reason: '클라우드 메타데이터 엔드포인트 차단(SSRF)' };
72
+ if (!allowHosts.includes(u.hostname))
73
+ return { ok: false, reason: `허용목록 외 호스트(${u.hostname})` };
74
+ return { ok: true, reason: 'ok' };
75
+ }
76
+ /** M2 — IP 가 사설/루프백/링크로컬/메타데이터/유니크로컬인가(SSRF 표적). */
77
+ function isPrivateIp(ip) {
78
+ const v = ip.trim().toLowerCase().replace(/^::ffff:/, ''); // IPv4-mapped 정규화
79
+ if (net.isIPv4(v)) {
80
+ const o = v.split('.').map(Number);
81
+ if (o[0] === 127 || o[0] === 10 || o[0] === 0)
82
+ return true; // 루프백/사설/this-network
83
+ if (o[0] === 192 && o[1] === 168)
84
+ return true; // 사설
85
+ if (o[0] === 172 && o[1] >= 16 && o[1] <= 31)
86
+ return true; // 사설
87
+ if (o[0] === 169 && o[1] === 254)
88
+ return true; // 링크로컬/메타데이터
89
+ if (o[0] === 100 && o[1] >= 64 && o[1] <= 127)
90
+ return true; // CGNAT
91
+ return false;
92
+ }
93
+ if (net.isIPv6(v)) {
94
+ if (v === '::1' || v === '::')
95
+ return true; // 루프백/미지정
96
+ if (v.startsWith('fe80'))
97
+ return true; // 링크로컬
98
+ if (v.startsWith('fc') || v.startsWith('fd'))
99
+ return true; // 유니크 로컬(ULA)
100
+ return false;
101
+ }
102
+ return true; // 알 수 없는 형식은 안전측으로 차단
103
+ }
104
+ /**
105
+ * M2 — DNS 리바인딩 방지: 호스트명을 *실제 resolve* 한 뒤 모든 IP가 공인인지 검사.
106
+ * 허용/공개 호스트명이 사설 IP로 가리켜도 차단. 외부 연결 직전 호출.
107
+ */
108
+ async function isSafeResolvedUrl(url, allowHosts, resolver) {
109
+ const base = isSafeMcpUrl(url, allowHosts);
110
+ if (!base.ok)
111
+ return base;
112
+ const host = new URL(url).hostname.replace(/^\[|\]$/g, '');
113
+ // 호스트명이 곧 IP면 그대로 검사(추가 resolve 불요).
114
+ if (net.isIP(host)) {
115
+ return isPrivateIp(host) ? { ok: false, reason: `사설/예약 IP 차단(${host})` } : { ok: true, reason: 'ok' };
116
+ }
117
+ let ips;
118
+ try {
119
+ ips = resolver ? await resolver(host) : (await dns_1.promises.lookup(host, { all: true })).map((a) => a.address);
120
+ }
121
+ catch (e) {
122
+ return { ok: false, reason: `DNS resolve 실패(${host}): ${e?.code ?? e?.message ?? 'err'}` };
123
+ }
124
+ if (!ips.length)
125
+ return { ok: false, reason: `resolve 결과 없음(${host})` };
126
+ const bad = ips.find((ip) => isPrivateIp(ip));
127
+ if (bad)
128
+ return { ok: false, reason: `DNS 리바인딩 의심 — 사설 IP로 resolve(${host}→${bad})` };
129
+ return { ok: true, reason: 'ok' };
130
+ }
131
+ // ── 도구 출력 오염 검증(신뢰 불가 입력) ─────────────────────────────────────
132
+ const INJECTION_PATTERNS = [
133
+ /ignore (previous|above) instructions/i,
134
+ /system prompt/i,
135
+ /you are now/i,
136
+ /<\s*script/i,
137
+ /\bexfiltrat/i,
138
+ ];
139
+ /**
140
+ * MCP 도구 출력 검증: (1) 기대 스키마 검증, (2) 프롬프트 인젝션 패턴 플래그.
141
+ * 인젝션 패턴이 있으면 ok=false(에이전트 컨텍스트로 환류 금지).
142
+ */
143
+ function sanitizeToolOutput(raw, isValid) {
144
+ const flags = [];
145
+ for (const re of INJECTION_PATTERNS)
146
+ if (re.test(raw))
147
+ flags.push(`injection:${re.source.slice(0, 24)}`);
148
+ let data;
149
+ try {
150
+ data = JSON.parse(raw);
151
+ }
152
+ catch {
153
+ return { ok: false, flags: [...flags, 'schema:JSON 파싱 실패'] };
154
+ }
155
+ if (!isValid(data))
156
+ flags.push('schema:불일치');
157
+ return { ok: flags.length === 0, data: flags.length === 0 ? data : undefined, flags };
158
+ }
159
+ // ── A2UI 격리 정책(CSP) + provenance ────────────────────────────────────────
160
+ /** 에이전트 생성 캔버스용 엄격 CSP — 인라인·eval·임의 네트워크 차단(허용 출처만). */
161
+ function a2uiCsp(allowConnect = []) {
162
+ const connect = ["'self'", ...allowConnect].join(' ');
163
+ return [
164
+ "default-src 'none'",
165
+ "script-src 'self'", // 인라인/eval 금지
166
+ "style-src 'self'",
167
+ "img-src 'self' data:",
168
+ `connect-src ${connect}`, // 임의 네트워크 금지(허용목록만)
169
+ "frame-ancestors 'self'",
170
+ "base-uri 'none'",
171
+ "form-action 'self'",
172
+ ].join('; ');
173
+ }
174
+ /** iframe sandbox 속성 — 동일출처/팝업/탑네비 차단(스크립트만 허용). */
175
+ exports.A2UI_SANDBOX = 'allow-scripts';
176
+ /** provenance 배너 마크업 — 사용자에게 "에이전트 생성" 출처를 명시(기만 방지). */
177
+ function provenanceBanner() {
178
+ return '<div role="note" data-n2world-provenance="agent-generated" style="position:sticky;top:0;background:#fde68a;color:#111;padding:6px 10px;font:600 12px sans-serif">⚠ 이 화면은 에이전트가 생성했습니다 — 입력 전 출처를 확인하세요</div>';
179
+ }
@@ -0,0 +1,75 @@
1
+ import { A2ATrustGate } from './agent-os-rd';
2
+ import { DataTier, Destination, TierGuard, ConsentGate, ConsentScope } from './beta';
3
+ export interface McpToolCall {
4
+ id: string;
5
+ /** MCP 도구 이름(= Macaroon scope·target). */
6
+ tool: string;
7
+ /** 데이터/행동 민감도 Tier. */
8
+ dataTier: DataTier;
9
+ /** 데이터 목적지. */
10
+ destination: Destination;
11
+ userId: string;
12
+ /** 선택적 경로 범위(path caveat 검증용). */
13
+ path?: string;
14
+ }
15
+ export interface AuthorizeOptions {
16
+ /** 외부 전송 시 요구할 동의 범위(기본 'llm-transmission'). */
17
+ requireConsentScope?: ConsentScope;
18
+ /** A2A 신뢰 평가용 peer id(있으면 신뢰 t 게이트 적용). */
19
+ peerId?: string;
20
+ /**
21
+ * 행동의 MCTS 계획 가치 v(있어도 인가 결정에 쓰지 않는다 — v↔t 분리 증명용 기록만).
22
+ * 고가치라도 저신뢰면 차단됨을 보이기 위해 받되, 게이트 로직은 v 를 참조하지 않는다.
23
+ */
24
+ value?: number;
25
+ }
26
+ export interface AuthorizationResult {
27
+ id: string;
28
+ allowed: boolean;
29
+ reason: string;
30
+ /** Macaroon 서명+target+expires 검증(HARD_GATE). */
31
+ hardGate: boolean;
32
+ /** 호출 도구가 Macaroon scope 와 일치. */
33
+ scopeOk: boolean;
34
+ /** 호출 dataTier 가 Macaroon tier 상한 이하. */
35
+ tierOk: boolean;
36
+ /** Tier-0 외부 반출 차단 통과(egress 허용 여부). */
37
+ egressAllowed: boolean;
38
+ /** Tier-0 외부 반출이 실제로 차단됐는가(관측 0/N 의 분자). */
39
+ tier0ExfilBlocked: boolean;
40
+ /** Tier 별 동의 충족. */
41
+ consentOk: boolean;
42
+ /** 신뢰 t(peerId 주어졌을 때). 아니면 null. */
43
+ trust: number | null;
44
+ /** 기록용(인가에 미사용) — v↔t 분리 증명. */
45
+ value: number | null;
46
+ }
47
+ /** MCP 도구 호출용 Macaroon 발행 — target=tool, scope=tool, tier 상한, 만료 caveat. */
48
+ export declare class MCPMacaroonMinter {
49
+ private readonly secret;
50
+ constructor(secret: string);
51
+ /**
52
+ * 사용자에게 도구 호출 Macaroon 을 발행한다. tier 상한 이하의 데이터에만 쓸 수 있고,
53
+ * scope(도구)·만료가 caveat 으로 묶인다(이후 attenuate 로만 추가 제한 가능 — 권한 상승 불가).
54
+ */
55
+ mint(userId: string, tool: string, tierCeiling: DataTier, expiresAtMs: number): string;
56
+ }
57
+ /**
58
+ * MCP 호출 경계 인가자. Macaroon(scope·tier·만료) + Tier 동의 + Tier-0 반출 차단 + 신뢰 t 를 결선한다.
59
+ * TierGuard/ConsentGate 는 B0 와 공유해 동의 체계를 중복하지 않는다(생성자 주입).
60
+ */
61
+ export declare class MCPAuthorizer {
62
+ private readonly secret;
63
+ private readonly tierGuard;
64
+ private readonly consent;
65
+ private readonly trustGate?;
66
+ constructor(secret: string, tierGuard?: TierGuard, consent?: ConsentGate, trustGate?: A2ATrustGate | undefined);
67
+ /** Tier-0 외부 반출 관측 통계(`관측 0/N`) — tier0ExfilObserved 는 항상 0 이어야 한다. */
68
+ egressStats(): {
69
+ externalAttempts: number;
70
+ tier0ExternalAttempts: number;
71
+ tier0ExfilObserved: number;
72
+ };
73
+ consentGate(): ConsentGate;
74
+ authorize(call: McpToolCall, token: string, opts?: AuthorizeOptions): AuthorizationResult;
75
+ }
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ // ============================================================================
3
+ // P5 — MCP-Macaroon 인가 + Tier 0/1/2 동의 (계획서 v2.4 §7 P5, 헌법 §2 신뢰 t)
4
+ // ----------------------------------------------------------------------------
5
+ // MCP(도구 연동) 호출 경계에 Macaroon 인가를 결선한다. 재사용(새 체계 금지·단순화):
6
+ // - `agent-os-rd.ts`: Macaroon/MacaroonVerifier(서명 체인·target·expires) + A2ATrustGate(신뢰 t)
7
+ // - `beta.ts`(B0): DataTier·TierGuard(Tier-0 반출 차단·관측 0/N) + ConsentGate(동의)
8
+ //
9
+ // 핵심 보장:
10
+ // 1) MCP 호출은 Macaroon 의 scope(도구)·tier 상한 caveat 로 인가된다(서명으로 무결성 보호).
11
+ // 2) 데이터/행동을 Tier 0/1/2 로 분류, Tier 별 동의 게이트 강제. **중복 동의 체계를 만들지 않는다.**
12
+ // 3) **Tier-0 데이터의 외부 반출은 무조건 차단 → `관측 0/N`**(TierGuard 가 실측 카운트).
13
+ // 4) 신뢰 t = HARD_GATE × reputation. **고가치(v)·저신뢰(t) 는 차단** — v 로 계층1 을 게이팅하지 않는다.
14
+ //
15
+ // 정직 고지(제1계명): `tier <=`·`scope =` caveat 는 Macaroon 서명 체인에 포함되어 무결성 보호되며,
16
+ // MacaroonVerifier(서명+target+expires) 통과 후 본 인가자가 의미를 강제한다. 위조/범위 밖은 차단.
17
+ // ============================================================================
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.MCPAuthorizer = exports.MCPMacaroonMinter = void 0;
20
+ const agent_os_rd_1 = require("./agent-os-rd");
21
+ const beta_1 = require("./beta");
22
+ const CAVEAT_TIER = 'tier <= ';
23
+ const CAVEAT_SCOPE = 'scope = ';
24
+ /** MCP 도구 호출용 Macaroon 발행 — target=tool, scope=tool, tier 상한, 만료 caveat. */
25
+ class MCPMacaroonMinter {
26
+ secret;
27
+ constructor(secret) {
28
+ this.secret = secret;
29
+ }
30
+ /**
31
+ * 사용자에게 도구 호출 Macaroon 을 발행한다. tier 상한 이하의 데이터에만 쓸 수 있고,
32
+ * scope(도구)·만료가 caveat 으로 묶인다(이후 attenuate 로만 추가 제한 가능 — 권한 상승 불가).
33
+ */
34
+ mint(userId, tool, tierCeiling, expiresAtMs) {
35
+ let m = agent_os_rd_1.Macaroon.create(this.secret, userId, tool); // target = tool
36
+ m = agent_os_rd_1.Macaroon.attenuate(m, `${CAVEAT_TIER}${tierCeiling}`);
37
+ m = agent_os_rd_1.Macaroon.attenuate(m, `${CAVEAT_SCOPE}${tool}`);
38
+ m = agent_os_rd_1.Macaroon.attenuate(m, `expires < ${expiresAtMs}`);
39
+ return agent_os_rd_1.Macaroon.serialize(m);
40
+ }
41
+ }
42
+ exports.MCPMacaroonMinter = MCPMacaroonMinter;
43
+ /**
44
+ * Macaroon caveat 에서 tier 상한·scope 를 파싱(없으면 null).
45
+ *
46
+ * 보안(attenuation 단조성): Macaroon 보유자는 root secret 없이 `attenuate` 로 caveat 를
47
+ * **덧붙일 수 있고** 서명 체인은 그대로 검증을 통과한다. 따라서 `tier <= 0` 토큰에
48
+ * `tier <= 2` 를 덧붙여 권한을 넓히는 시도가 가능하다. caveat 는 **제한만** 할 수 있어야
49
+ * 하므로, 여러 `tier <= ` caveat 이 있으면 **최솟값(가장 제한적)** 을 취한다(last-wins 금지).
50
+ */
51
+ function parseCaveats(token) {
52
+ try {
53
+ const m = agent_os_rd_1.Macaroon.deserialize(token);
54
+ let tierCeiling = null;
55
+ let scope = null;
56
+ for (const c of m.caveats) {
57
+ if (c.startsWith(CAVEAT_TIER)) {
58
+ const n = parseInt(c.substring(CAVEAT_TIER.length), 10);
59
+ // 가장 제한적(min)으로만 좁힌다 — 덧붙인 더 느슨한 상한으로 권한 상승 불가.
60
+ if (n === 0 || n === 1 || n === 2) {
61
+ tierCeiling = tierCeiling === null ? n : Math.min(tierCeiling, n);
62
+ }
63
+ }
64
+ else if (c.startsWith(CAVEAT_SCOPE)) {
65
+ // scope 도 동일 원칙: 한 번 정해진 scope 와 다른 값이 덧붙으면 충돌 → 차단(null).
66
+ // (scope 자체는 target caveat 이중검증으로도 보호되나, 방어심층화로 일관 적용.)
67
+ const s = c.substring(CAVEAT_SCOPE.length);
68
+ scope = scope === null ? s : scope === s ? s : '\0conflict';
69
+ }
70
+ }
71
+ return { tierCeiling, scope };
72
+ }
73
+ catch {
74
+ return { tierCeiling: null, scope: null };
75
+ }
76
+ }
77
+ /**
78
+ * MCP 호출 경계 인가자. Macaroon(scope·tier·만료) + Tier 동의 + Tier-0 반출 차단 + 신뢰 t 를 결선한다.
79
+ * TierGuard/ConsentGate 는 B0 와 공유해 동의 체계를 중복하지 않는다(생성자 주입).
80
+ */
81
+ class MCPAuthorizer {
82
+ secret;
83
+ tierGuard;
84
+ consent;
85
+ trustGate;
86
+ constructor(secret, tierGuard = new beta_1.TierGuard(), consent = new beta_1.ConsentGate(), trustGate) {
87
+ this.secret = secret;
88
+ this.tierGuard = tierGuard;
89
+ this.consent = consent;
90
+ this.trustGate = trustGate;
91
+ }
92
+ /** Tier-0 외부 반출 관측 통계(`관측 0/N`) — tier0ExfilObserved 는 항상 0 이어야 한다. */
93
+ egressStats() {
94
+ return this.tierGuard.stats();
95
+ }
96
+ consentGate() {
97
+ return this.consent;
98
+ }
99
+ authorize(call, token, opts = {}) {
100
+ const now = Date.now();
101
+ const ctx = { target: call.tool, time: now, path: call.path ?? '' };
102
+ const base = {
103
+ id: call.id,
104
+ allowed: false,
105
+ reason: '',
106
+ hardGate: false,
107
+ scopeOk: false,
108
+ tierOk: false,
109
+ egressAllowed: false,
110
+ tier0ExfilBlocked: false,
111
+ consentOk: false,
112
+ trust: null,
113
+ value: opts.value ?? null,
114
+ };
115
+ // 1) HARD_GATE: Macaroon 서명 체인 + target(=tool) + expires 검증.
116
+ const hardGate = agent_os_rd_1.MacaroonVerifier.verify(token, this.secret, ctx);
117
+ base.hardGate = hardGate;
118
+ if (!hardGate) {
119
+ return { ...base, reason: 'HARD_GATE 실패: Macaroon 서명/target/만료 위반' };
120
+ }
121
+ // 2) scope·tier 상한 caveat 강제(서명으로 무결성 보호된 caveat).
122
+ const { tierCeiling, scope } = parseCaveats(token);
123
+ base.scopeOk = scope === call.tool;
124
+ if (!base.scopeOk) {
125
+ return { ...base, reason: `scope 불일치: 토큰 scope=${scope} ≠ 호출 도구=${call.tool}` };
126
+ }
127
+ base.tierOk = tierCeiling !== null && call.dataTier <= tierCeiling;
128
+ if (!base.tierOk) {
129
+ return { ...base, reason: `tier 상한 초과: 호출 Tier=${call.dataTier} > 토큰 상한=${tierCeiling}` };
130
+ }
131
+ // 3) Tier-0 외부 반출 차단(TierGuard — 관측 0/N). 모든 시도/차단은 실측 기록.
132
+ const eg = this.tierGuard.guardEgress(call.dataTier, call.destination);
133
+ base.egressAllowed = eg.allowed;
134
+ base.tier0ExfilBlocked = call.dataTier === 0 && call.destination === 'external' && !eg.allowed;
135
+ if (!eg.allowed) {
136
+ return { ...base, reason: eg.reason }; // Tier-0 외부 반출 차단(관측 0/N 보장)
137
+ }
138
+ // 4) Tier 동의: 외부 전송이면서 Tier-0 이 아닌 경우 동의 필요(Tier-0 은 이미 3에서 차단).
139
+ if (call.destination === 'external') {
140
+ const scopeNeeded = opts.requireConsentScope ?? 'llm-transmission';
141
+ base.consentOk = this.consent.hasConsent(call.userId, scopeNeeded);
142
+ if (!base.consentOk) {
143
+ return { ...base, reason: `동의 필요: ${scopeNeeded} (Tier ${call.dataTier} 외부 전송 — 미동의 차단)` };
144
+ }
145
+ }
146
+ else {
147
+ base.consentOk = true; // 로컬 목적지는 외부 동의 불요(헌법 제4조 로컬 기억)
148
+ }
149
+ // 5) 신뢰 t = HARD_GATE × reputation. **고가치라도 저신뢰면 차단**(v↔t 분리).
150
+ if (this.trustGate && opts.peerId) {
151
+ const r = this.trustGate.evaluate(opts.peerId, token, ctx);
152
+ base.trust = r.trust;
153
+ if (!r.allowed) {
154
+ // opts.value(고가치)는 결정에 쓰지 않는다 — 신뢰 t 만으로 차단.
155
+ return { ...base, reason: `신뢰 미달(t=${r.trust.toFixed(3)}) — 고가치라도 차단(v↔t 분리)` };
156
+ }
157
+ }
158
+ return { ...base, allowed: true, reason: 'authorized' };
159
+ }
160
+ }
161
+ exports.MCPAuthorizer = MCPAuthorizer;
@@ -0,0 +1,36 @@
1
+ import { SchedulerConfig } from './agent-os-rd';
2
+ export interface KernelControlResult {
3
+ /** 입력 정규화 가치 v_norm∈[0,1]. */
4
+ vNorm: number;
5
+ /** 식(2)로 계산한 의도 cgroups cpu.weight (플랫폼 무관, 항상 산출). */
6
+ weight: number;
7
+ /** 실제 cpu.weight 파일 기입 성공(Linux+유효 cgroup+권한만 true). 비-Linux=false(정직). */
8
+ cgroupWritten: boolean;
9
+ /** 실제 eBPF 맵 갱신 성공(Linux+CAP_BPF만 true). 비-Linux=false(정직). */
10
+ ebpfWritten: boolean;
11
+ /** eBPF 맵이 활성인가(Linux+권한). */
12
+ ebpfMapActive: boolean;
13
+ platform: string;
14
+ isLinux: boolean;
15
+ note: string;
16
+ }
17
+ /**
18
+ * MCTS 가치 → 커널 자원 제어 결선 브리지. v_norm 한 번으로 식(2) 가중치 산출 + cgroup/eBPF 기입을 모두 시도한다.
19
+ * 비-Linux 환경에선 의도 가중치만 계산하고 실기입은 정직하게 false 로 보고한다.
20
+ */
21
+ export declare class MctsKernelBridge {
22
+ private driver;
23
+ private ebpf;
24
+ constructor(cfg?: Partial<SchedulerConfig>);
25
+ /** eBPF 맵 활성 여부(Linux+CAP_BPF). 비-Linux/비-권한이면 false. */
26
+ ebpfActive(): boolean;
27
+ /** 식(2)로 계산한 의도 가중치(플랫폼 무관). 기입 시도 없이 값만. */
28
+ weightFor(vNorm: number): number;
29
+ /**
30
+ * v_norm → 식(2) weight → cgroup cpu.weight 기입 + eBPF 맵(thread_id→v) 갱신.
31
+ * 경로를 끝까지 연결한다. 실기입 성공 여부는 플랫폼·권한에 따라 정직히 보고.
32
+ */
33
+ applyValue(cgroupPath: string, vNorm: number, threadId: number): KernelControlResult;
34
+ /** 원시 Q와 분포(min,max)로부터 정규화 후 결선. */
35
+ applyRawValue(cgroupPath: string, q: number, qMin: number, qMax: number, threadId: number): KernelControlResult;
36
+ }
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ // ============================================================================
3
+ // P4 — MCTS 가치 v → 커널 자원 제어(cgroups/eBPF) 결선 (계획서 v2.4 §7 P4, §2.1)
4
+ // ----------------------------------------------------------------------------
5
+ // 가치 v_norm → 식(2) 가중치 w(v_norm) → cgroups cpu.weight 실기입 + eBPF 맵 갱신까지 **끝까지 결선**한다.
6
+ // 재사용: `EbpfSchedulerDriver`(식(2)·set_cgroup_cpu_weight) + Rust `EbpfMapScheduler`(raw bpf() 맵).
7
+ //
8
+ // 정직 고지(제1계명): 가중치 w 는 플랫폼 무관하게 항상 계산(의도 제어)되지만, **실제 커널 기입은
9
+ // Linux + 권한에서만 true**다. 비-Linux/비-권한은 **정직하게 false**를 돌려준다(가짜 true 금지).
10
+ // 과거 `update_ebpf_map`/`set_cgroup_cpu_weight` 가 true 반환 스텁이던 전력을 반복하지 않는다.
11
+ // ============================================================================
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.MctsKernelBridge = void 0;
47
+ const os = __importStar(require("os"));
48
+ const core_1 = require("@n2world/core");
49
+ const agent_os_rd_1 = require("./agent-os-rd");
50
+ /**
51
+ * MCTS 가치 → 커널 자원 제어 결선 브리지. v_norm 한 번으로 식(2) 가중치 산출 + cgroup/eBPF 기입을 모두 시도한다.
52
+ * 비-Linux 환경에선 의도 가중치만 계산하고 실기입은 정직하게 false 로 보고한다.
53
+ */
54
+ class MctsKernelBridge {
55
+ driver;
56
+ ebpf;
57
+ constructor(cfg = {}) {
58
+ this.driver = new agent_os_rd_1.EbpfSchedulerDriver(cfg);
59
+ this.ebpf = new core_1.EbpfMapScheduler();
60
+ }
61
+ /** eBPF 맵 활성 여부(Linux+CAP_BPF). 비-Linux/비-권한이면 false. */
62
+ ebpfActive() {
63
+ return this.ebpf.mapActive();
64
+ }
65
+ /** 식(2)로 계산한 의도 가중치(플랫폼 무관). 기입 시도 없이 값만. */
66
+ weightFor(vNorm) {
67
+ return this.driver.weightForValue(vNorm);
68
+ }
69
+ /**
70
+ * v_norm → 식(2) weight → cgroup cpu.weight 기입 + eBPF 맵(thread_id→v) 갱신.
71
+ * 경로를 끝까지 연결한다. 실기입 성공 여부는 플랫폼·권한에 따라 정직히 보고.
72
+ */
73
+ applyValue(cgroupPath, vNorm, threadId) {
74
+ const isLinux = os.platform() === 'linux';
75
+ const { weight, success: cgroupWritten } = this.driver.adjustResourceByValue(cgroupPath, vNorm);
76
+ const ebpfWritten = this.ebpf.updateEbpfMap(threadId, Math.max(0, Math.min(1, vNorm)));
77
+ const ebpfMapActive = this.ebpf.mapActive();
78
+ return {
79
+ vNorm: Math.max(0, Math.min(1, vNorm)),
80
+ weight,
81
+ cgroupWritten,
82
+ ebpfWritten,
83
+ ebpfMapActive,
84
+ platform: os.platform(),
85
+ isLinux,
86
+ note: isLinux
87
+ ? cgroupWritten || ebpfWritten
88
+ ? '커널 결선 활성(Linux): 실기입 성공.'
89
+ : 'Linux 이나 권한/cgroup 경로 부재 — 의도 가중치만 적용(정직 false).'
90
+ : '비-Linux: 의도 가중치만 계산. cgroup/eBPF 실기입 없음(정직 false — 가짜 true 아님).',
91
+ };
92
+ }
93
+ /** 원시 Q와 분포(min,max)로부터 정규화 후 결선. */
94
+ applyRawValue(cgroupPath, q, qMin, qMax, threadId) {
95
+ const vNorm = agent_os_rd_1.EbpfSchedulerDriver.normalize(q, qMin, qMax);
96
+ return this.applyValue(cgroupPath, vNorm, threadId);
97
+ }
98
+ }
99
+ exports.MctsKernelBridge = MctsKernelBridge;
@@ -0,0 +1,79 @@
1
+ import { KnowledgeGraph } from './knowledge-graph';
2
+ export interface ActionItem {
3
+ id: string;
4
+ content: string;
5
+ }
6
+ export interface ActionPrior {
7
+ id: string;
8
+ prior: number;
9
+ }
10
+ export interface EmbeddingPriorOptions {
11
+ /** softmax 온도(>0). 낮을수록 상위 후보 집중. */
12
+ temperature?: number;
13
+ /** P2 그래프(있으면) — 컨텍스트 관련 노드의 이웃 액션에 사전확률 부스트. */
14
+ graph?: KnowledgeGraph;
15
+ /** 그래프 부스트 배수(기본 1.5). 1 이면 부스트 없음. */
16
+ graphBoost?: number;
17
+ /** 그래프 부스트 기준 노드 id 들(보통 컨텍스트가 가리키는 항목). */
18
+ graphAnchors?: string[];
19
+ }
20
+ /**
21
+ * P1 임베딩 + (옵션)P2 그래프로 사전확률 P(s,a)를 만든다(합=1).
22
+ * graph/graphAnchors 가 주어지면, 앵커 노드와 참조/의존으로 연결된 액션의 prior 를 곱셈 부스트 후 재정규화.
23
+ */
24
+ export declare function embeddingWeightedPrior(actions: ActionItem[], context: string, opts?: EmbeddingPriorOptions): ActionPrior[];
25
+ /** 균등 사전확률(비교군 baseline). */
26
+ export declare function uniformPrior(actions: ActionItem[]): ActionPrior[];
27
+ interface ArmStat {
28
+ id: string;
29
+ n: number;
30
+ w: number;
31
+ prior: number;
32
+ }
33
+ /** 식(1) PUCT 선택: argmax[ Q + c_puct·P·√(ΣN)/(1+n) ]. */
34
+ export declare function puctSelect(stats: ArmStat[], cPuct: number): ArmStat;
35
+ export interface PuctSearchResult {
36
+ /** 가장 많이 방문된 액션이 target 과 처음 일치한 시뮬 번호(낮을수록 효율). 끝까지 불일치면 sims+1. */
37
+ simsToConverge: number;
38
+ /** 종료 시 최다 방문 액션. */
39
+ finalBestId: string;
40
+ /** target 액션의 누적 방문수. */
41
+ targetVisits: number;
42
+ /** 누적 후회(regret) = Σ(maxTrueValue − trueValue[선택]). 낮을수록 좋음. */
43
+ regret: number;
44
+ }
45
+ /**
46
+ * 사전확률 priors 로 PUCT 탐색을 sims 회 돌리고 효율 지표를 반환한다.
47
+ * 보상 = trueValue[선택] + 가우시안 잡음(외부 오라클). target = trueValue 최대 액션.
48
+ * @param rnd 결정적 난수(시드 고정) — 재현성.
49
+ */
50
+ export declare function runPuctSearch(actions: ActionItem[], priors: ActionPrior[], trueValue: Record<string, number>, sims: number, cPuct: number, rnd: () => number, noiseSd?: number): PuctSearchResult;
51
+ export interface PriorEfficiencyComparison {
52
+ uniform: {
53
+ simsToConvergeMean: number;
54
+ regretMean: number;
55
+ convergedRate: number;
56
+ };
57
+ embedding: {
58
+ simsToConvergeMean: number;
59
+ regretMean: number;
60
+ convergedRate: number;
61
+ };
62
+ /** 평균 수렴 시뮬 절감(uniform − embedding). 양수면 임베딩 사전확률이 더 빠름. */
63
+ simsToConvergeSaved: number;
64
+ trials: number;
65
+ }
66
+ /**
67
+ * 균등 vs 임베딩 사전확률의 PUCT 탐색 효율을 다회 비교한다(결정적 시드).
68
+ * trueValue 는 호출자가 주는 외부 오라클(임베딩과 독립적으로 정한 진짜 가치).
69
+ */
70
+ export declare function comparePriorEfficiency(actions: ActionItem[], context: string, trueValue: Record<string, number>, opts?: {
71
+ sims?: number;
72
+ cPuct?: number;
73
+ trials?: number;
74
+ seed?: number;
75
+ priorOpts?: EmbeddingPriorOptions;
76
+ }): PriorEfficiencyComparison;
77
+ /** 결정적 LCG(시드 고정) — 재현 가능한 측정. */
78
+ export declare function lcg(seed: number): () => number;
79
+ export {};