@gethelio/proxy 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +99 -15
- package/dist/index.d.ts +24 -0
- package/dist/index.js +79 -3
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -5303,13 +5303,22 @@ var installScanBody = z4.object({
|
|
|
5303
5303
|
}),
|
|
5304
5304
|
metadata: metadataSchema
|
|
5305
5305
|
});
|
|
5306
|
+
var evidenceEntrySchema = z4.object({
|
|
5307
|
+
evidence_key: z4.string().min(1),
|
|
5308
|
+
evidence_data: z4.unknown().refine((v) => v !== void 0, { message: "Required" }),
|
|
5309
|
+
ttl_seconds: z4.number().int().positive().optional()
|
|
5310
|
+
});
|
|
5306
5311
|
var auditBody = z4.object({
|
|
5307
5312
|
evaluation_id: z4.string().min(1),
|
|
5308
5313
|
status: z4.enum(["success", "error", "not_executed"]),
|
|
5309
5314
|
error: z4.string().optional(),
|
|
5310
5315
|
duration_ms: z4.number().optional(),
|
|
5311
5316
|
result: z4.unknown().optional(),
|
|
5312
|
-
actual_amount: z4.number().optional()
|
|
5317
|
+
actual_amount: z4.number().optional(),
|
|
5318
|
+
// No `.max()` / size refinement here on purpose (issue #11): caps are
|
|
5319
|
+
// enforced per-entry in GovernanceService.populateEvidence as soft-drops, so
|
|
5320
|
+
// an over-cap entry never 400s away the audit row for a call that already ran.
|
|
5321
|
+
evidence: z4.array(evidenceEntrySchema).optional()
|
|
5313
5322
|
});
|
|
5314
5323
|
var resolveBody = z4.object({
|
|
5315
5324
|
resolution: z4.enum(["approved", "denied", "timeout", "cancelled"]),
|
|
@@ -5411,10 +5420,19 @@ function auditPayloadHash(data) {
|
|
|
5411
5420
|
error: data.error ?? null,
|
|
5412
5421
|
duration_ms: data.duration_ms ?? null,
|
|
5413
5422
|
result: data.result ?? null,
|
|
5414
|
-
actual_amount: data.actual_amount ?? null
|
|
5423
|
+
actual_amount: data.actual_amount ?? null,
|
|
5424
|
+
evidence: canonicalEvidence(data.evidence)
|
|
5415
5425
|
};
|
|
5416
5426
|
return createHash2("sha256").update(canonicalize(semantic)).digest("hex");
|
|
5417
5427
|
}
|
|
5428
|
+
function canonicalEvidence(evidence) {
|
|
5429
|
+
if (!evidence || evidence.length === 0) return null;
|
|
5430
|
+
return evidence.map((e) => ({
|
|
5431
|
+
evidence_key: e.evidence_key,
|
|
5432
|
+
evidence_data: e.evidence_data ?? null,
|
|
5433
|
+
ttl_seconds: e.ttl_seconds ?? null
|
|
5434
|
+
})).map((norm) => ({ sortKey: canonicalize(norm), norm })).sort((a, b) => a.sortKey < b.sortKey ? -1 : a.sortKey > b.sortKey ? 1 : 0).map((x) => x.norm);
|
|
5435
|
+
}
|
|
5418
5436
|
function asStatus(status) {
|
|
5419
5437
|
return status;
|
|
5420
5438
|
}
|
|
@@ -5547,6 +5565,8 @@ var MAX_TOOL_INPUT_BYTES = 64 * 1024;
|
|
|
5547
5565
|
var MAX_PENDING_COUNT = 1e4;
|
|
5548
5566
|
var MAX_PENDING_BYTES = 64 * 1024 * 1024;
|
|
5549
5567
|
var MAX_SENDER_KEYS = 5e4;
|
|
5568
|
+
var MAX_EVIDENCE_ENTRIES = 16;
|
|
5569
|
+
var MAX_EVIDENCE_BYTES = 64 * 1024;
|
|
5550
5570
|
var SWEEP_INTERVAL_MS2 = 3e4;
|
|
5551
5571
|
var GovernanceService = class {
|
|
5552
5572
|
policy;
|
|
@@ -5837,6 +5857,7 @@ var GovernanceService = class {
|
|
|
5837
5857
|
if (callHappened && this.evidenceStore && entry.sessionId) {
|
|
5838
5858
|
this.evidenceStore.recordToolCall(entry.sessionId, entry.toolName, req.status === "success");
|
|
5839
5859
|
}
|
|
5860
|
+
const evidenceOutcomes = this.populateEvidence(req, entry);
|
|
5840
5861
|
const auditId = this.writeAudit({
|
|
5841
5862
|
timestampIso: entry.timestampIso,
|
|
5842
5863
|
origin: entry.origin,
|
|
@@ -5866,7 +5887,62 @@ var GovernanceService = class {
|
|
|
5866
5887
|
finalizedBy: "audit",
|
|
5867
5888
|
expiresAtMs: this.now() + this.ttlMs
|
|
5868
5889
|
});
|
|
5869
|
-
|
|
5890
|
+
const body = { ok: true, audit_record_id: auditId };
|
|
5891
|
+
if (evidenceOutcomes) body["evidence"] = evidenceOutcomes;
|
|
5892
|
+
return { status: 201, body };
|
|
5893
|
+
}
|
|
5894
|
+
/**
|
|
5895
|
+
* Write the optional `/audit` evidence entries for a successful call
|
|
5896
|
+
* (issue #11), returning a per-entry outcome list — or `undefined`
|
|
5897
|
+
* when there is nothing to report (non-success status, or no evidence
|
|
5898
|
+
* supplied). Caps are enforced here, NOT in route validation, so an over-cap
|
|
5899
|
+
* entry soft-drops without discarding the audit row: entries past
|
|
5900
|
+
* `MAX_EVIDENCE_ENTRIES` → `too_many`; oversized `evidence_data` →
|
|
5901
|
+
* `too_large`; no evidence store on the service → `evidence_unavailable`;
|
|
5902
|
+
* a sessionless evaluation → `no_session`; the store's own rejections
|
|
5903
|
+
* (`key_not_in_policy_allowlist`, `closed`) pass through as the per-entry
|
|
5904
|
+
* reason. None of these fail the audit.
|
|
5905
|
+
*/
|
|
5906
|
+
populateEvidence(req, entry) {
|
|
5907
|
+
if (req.status !== "success" || !req.evidence || req.evidence.length === 0) {
|
|
5908
|
+
return void 0;
|
|
5909
|
+
}
|
|
5910
|
+
const outcomes = [];
|
|
5911
|
+
for (let i = 0; i < req.evidence.length; i++) {
|
|
5912
|
+
const e = req.evidence[i];
|
|
5913
|
+
if (!e) continue;
|
|
5914
|
+
if (i >= MAX_EVIDENCE_ENTRIES) {
|
|
5915
|
+
outcomes.push({ evidence_key: e.evidence_key, stored: false, reason: "too_many" });
|
|
5916
|
+
continue;
|
|
5917
|
+
}
|
|
5918
|
+
const bytes = Buffer.byteLength(canonicalize(e.evidence_data ?? null), "utf8");
|
|
5919
|
+
if (bytes > MAX_EVIDENCE_BYTES) {
|
|
5920
|
+
outcomes.push({ evidence_key: e.evidence_key, stored: false, reason: "too_large" });
|
|
5921
|
+
continue;
|
|
5922
|
+
}
|
|
5923
|
+
if (!this.evidenceStore) {
|
|
5924
|
+
outcomes.push({
|
|
5925
|
+
evidence_key: e.evidence_key,
|
|
5926
|
+
stored: false,
|
|
5927
|
+
reason: "evidence_unavailable"
|
|
5928
|
+
});
|
|
5929
|
+
continue;
|
|
5930
|
+
}
|
|
5931
|
+
if (!entry.sessionId) {
|
|
5932
|
+
outcomes.push({ evidence_key: e.evidence_key, stored: false, reason: "no_session" });
|
|
5933
|
+
continue;
|
|
5934
|
+
}
|
|
5935
|
+
const result = this.evidenceStore.putEvidence(entry.sessionId, {
|
|
5936
|
+
evidence_key: e.evidence_key,
|
|
5937
|
+
data: e.evidence_data,
|
|
5938
|
+
tool_name: entry.toolName,
|
|
5939
|
+
ttl_seconds: e.ttl_seconds
|
|
5940
|
+
});
|
|
5941
|
+
outcomes.push(
|
|
5942
|
+
result.stored ? { evidence_key: e.evidence_key, stored: true } : { evidence_key: e.evidence_key, stored: false, reason: result.reason }
|
|
5943
|
+
);
|
|
5944
|
+
}
|
|
5945
|
+
return outcomes;
|
|
5870
5946
|
}
|
|
5871
5947
|
// -------------------------------------------------------------------------
|
|
5872
5948
|
// POST /install-scan — evaluates install-time policy (issue #13)
|
|
@@ -7969,6 +8045,13 @@ function warnIfDashboardOpenMode(config, log = console.error) {
|
|
|
7969
8045
|
);
|
|
7970
8046
|
return true;
|
|
7971
8047
|
}
|
|
8048
|
+
function warnIfNoEnforcement(policy, log = console.error) {
|
|
8049
|
+
if (policy.rules.length > 0 || policy.defaultAction !== "allow" || policy.dryRun) return false;
|
|
8050
|
+
log(
|
|
8051
|
+
'[helio] No policy rules are loaded and the default action is "allow" - Helio is recording an audit trail but NOT blocking anything. Add rules under `policies:` in helio.yaml to start enforcing (see docs/policies.md).'
|
|
8052
|
+
);
|
|
8053
|
+
return true;
|
|
8054
|
+
}
|
|
7972
8055
|
|
|
7973
8056
|
// src/crash-drain.ts
|
|
7974
8057
|
var hooks = [];
|
|
@@ -8041,18 +8124,6 @@ upstream:
|
|
|
8041
8124
|
# headers:
|
|
8042
8125
|
# Authorization: "Bearer \${UPSTREAM_TOKEN}"
|
|
8043
8126
|
|
|
8044
|
-
# Operator dashboard + approval REST API. Bound to 127.0.0.1 by default \u2014 do
|
|
8045
|
-
# not change to 0.0.0.0 without putting an authenticating reverse proxy in
|
|
8046
|
-
# front. dashboard.api_secret is the manual dashboard login secret and also
|
|
8047
|
-
# supports machine Bearer auth for sideband API clients. Store it safely; it
|
|
8048
|
-
# stays valid until you rotate it. Rotate by editing this file and restarting
|
|
8049
|
-
# (or hot-reloading) the proxy. Rotation invalidates active dashboard sessions.
|
|
8050
|
-
dashboard:
|
|
8051
|
-
enabled: true
|
|
8052
|
-
port: 3100
|
|
8053
|
-
host: 127.0.0.1
|
|
8054
|
-
api_secret: "${apiSecret}"
|
|
8055
|
-
|
|
8056
8127
|
# listen:
|
|
8057
8128
|
# port: 3000
|
|
8058
8129
|
# host: 127.0.0.1
|
|
@@ -8073,6 +8144,18 @@ dashboard:
|
|
|
8073
8144
|
# retention: 90d
|
|
8074
8145
|
# include_responses: true
|
|
8075
8146
|
|
|
8147
|
+
# Operator dashboard + approval REST API. Bound to 127.0.0.1 by default \u2014 do
|
|
8148
|
+
# not change to 0.0.0.0 without putting an authenticating reverse proxy in
|
|
8149
|
+
# front. dashboard.api_secret is the manual dashboard login secret and also
|
|
8150
|
+
# supports machine Bearer auth for sideband API clients. Store it safely; it
|
|
8151
|
+
# stays valid until you rotate it. Rotate by editing this file and restarting
|
|
8152
|
+
# (or hot-reloading) the proxy. Rotation invalidates active dashboard sessions.
|
|
8153
|
+
dashboard:
|
|
8154
|
+
enabled: true
|
|
8155
|
+
port: 3100
|
|
8156
|
+
host: 127.0.0.1
|
|
8157
|
+
api_secret: "${apiSecret}"
|
|
8158
|
+
|
|
8076
8159
|
# sdk:
|
|
8077
8160
|
# enabled: false
|
|
8078
8161
|
# port: 3200
|
|
@@ -8368,6 +8451,7 @@ async function startCommand(configPath, options) {
|
|
|
8368
8451
|
console.error(
|
|
8369
8452
|
`Policies: ${String(ruleCount)} rule${ruleCount !== 1 ? "s" : ""} loaded (default: ${policy.defaultAction})`
|
|
8370
8453
|
);
|
|
8454
|
+
warnIfNoEnforcement(policy);
|
|
8371
8455
|
if (config.upstream.transport === "stdio") {
|
|
8372
8456
|
console.error(`Upstream: ${config.upstream.command ?? ""} (stdio)`);
|
|
8373
8457
|
} else {
|
package/dist/index.d.ts
CHANGED
|
@@ -1932,6 +1932,11 @@ interface InstallScanInput {
|
|
|
1932
1932
|
};
|
|
1933
1933
|
readonly metadata: Record<string, unknown> | null;
|
|
1934
1934
|
}
|
|
1935
|
+
interface AuditEvidenceInput {
|
|
1936
|
+
readonly evidence_key: string;
|
|
1937
|
+
readonly evidence_data: unknown;
|
|
1938
|
+
readonly ttl_seconds?: number;
|
|
1939
|
+
}
|
|
1935
1940
|
interface AuditInput {
|
|
1936
1941
|
readonly evaluation_id: string;
|
|
1937
1942
|
readonly status: 'success' | 'error' | 'not_executed';
|
|
@@ -1939,6 +1944,12 @@ interface AuditInput {
|
|
|
1939
1944
|
readonly duration_ms?: number;
|
|
1940
1945
|
readonly result?: unknown;
|
|
1941
1946
|
readonly actual_amount?: number;
|
|
1947
|
+
/**
|
|
1948
|
+
* Optional evidence to populate on a successfully-audited call (issue #11). Adapter-scoped, single-token evidence write: bound to the pending
|
|
1949
|
+
* evaluation's session/tool, success-only, first-finalize-only. Every
|
|
1950
|
+
* per-entry failure is soft (reported, never request-fatal) — see audit().
|
|
1951
|
+
*/
|
|
1952
|
+
readonly evidence?: ReadonlyArray<AuditEvidenceInput>;
|
|
1942
1953
|
}
|
|
1943
1954
|
interface ResolveApprovalInput {
|
|
1944
1955
|
readonly resolution: 'approved' | 'denied' | 'timeout' | 'cancelled';
|
|
@@ -2004,6 +2015,19 @@ declare class GovernanceService {
|
|
|
2004
2015
|
updatePolicy(policy: CompiledPolicy): void;
|
|
2005
2016
|
evaluate(req: EvaluateInput): ServiceResult;
|
|
2006
2017
|
audit(req: AuditInput, payloadHash: string): ServiceResult;
|
|
2018
|
+
/**
|
|
2019
|
+
* Write the optional `/audit` evidence entries for a successful call
|
|
2020
|
+
* (issue #11), returning a per-entry outcome list — or `undefined`
|
|
2021
|
+
* when there is nothing to report (non-success status, or no evidence
|
|
2022
|
+
* supplied). Caps are enforced here, NOT in route validation, so an over-cap
|
|
2023
|
+
* entry soft-drops without discarding the audit row: entries past
|
|
2024
|
+
* `MAX_EVIDENCE_ENTRIES` → `too_many`; oversized `evidence_data` →
|
|
2025
|
+
* `too_large`; no evidence store on the service → `evidence_unavailable`;
|
|
2026
|
+
* a sessionless evaluation → `no_session`; the store's own rejections
|
|
2027
|
+
* (`key_not_in_policy_allowlist`, `closed`) pass through as the per-entry
|
|
2028
|
+
* reason. None of these fail the audit.
|
|
2029
|
+
*/
|
|
2030
|
+
private populateEvidence;
|
|
2007
2031
|
installScan(req: InstallScanInput): ServiceResult;
|
|
2008
2032
|
/** First-match-wins evaluation of the compiled install policy (issue #13). */
|
|
2009
2033
|
private evaluateInstall;
|
package/dist/index.js
CHANGED
|
@@ -4584,13 +4584,22 @@ var installScanBody = z4.object({
|
|
|
4584
4584
|
}),
|
|
4585
4585
|
metadata: metadataSchema
|
|
4586
4586
|
});
|
|
4587
|
+
var evidenceEntrySchema = z4.object({
|
|
4588
|
+
evidence_key: z4.string().min(1),
|
|
4589
|
+
evidence_data: z4.unknown().refine((v) => v !== void 0, { message: "Required" }),
|
|
4590
|
+
ttl_seconds: z4.number().int().positive().optional()
|
|
4591
|
+
});
|
|
4587
4592
|
var auditBody = z4.object({
|
|
4588
4593
|
evaluation_id: z4.string().min(1),
|
|
4589
4594
|
status: z4.enum(["success", "error", "not_executed"]),
|
|
4590
4595
|
error: z4.string().optional(),
|
|
4591
4596
|
duration_ms: z4.number().optional(),
|
|
4592
4597
|
result: z4.unknown().optional(),
|
|
4593
|
-
actual_amount: z4.number().optional()
|
|
4598
|
+
actual_amount: z4.number().optional(),
|
|
4599
|
+
// No `.max()` / size refinement here on purpose (issue #11): caps are
|
|
4600
|
+
// enforced per-entry in GovernanceService.populateEvidence as soft-drops, so
|
|
4601
|
+
// an over-cap entry never 400s away the audit row for a call that already ran.
|
|
4602
|
+
evidence: z4.array(evidenceEntrySchema).optional()
|
|
4594
4603
|
});
|
|
4595
4604
|
var resolveBody = z4.object({
|
|
4596
4605
|
resolution: z4.enum(["approved", "denied", "timeout", "cancelled"]),
|
|
@@ -4692,10 +4701,19 @@ function auditPayloadHash(data) {
|
|
|
4692
4701
|
error: data.error ?? null,
|
|
4693
4702
|
duration_ms: data.duration_ms ?? null,
|
|
4694
4703
|
result: data.result ?? null,
|
|
4695
|
-
actual_amount: data.actual_amount ?? null
|
|
4704
|
+
actual_amount: data.actual_amount ?? null,
|
|
4705
|
+
evidence: canonicalEvidence(data.evidence)
|
|
4696
4706
|
};
|
|
4697
4707
|
return createHash2("sha256").update(canonicalize(semantic)).digest("hex");
|
|
4698
4708
|
}
|
|
4709
|
+
function canonicalEvidence(evidence) {
|
|
4710
|
+
if (!evidence || evidence.length === 0) return null;
|
|
4711
|
+
return evidence.map((e) => ({
|
|
4712
|
+
evidence_key: e.evidence_key,
|
|
4713
|
+
evidence_data: e.evidence_data ?? null,
|
|
4714
|
+
ttl_seconds: e.ttl_seconds ?? null
|
|
4715
|
+
})).map((norm) => ({ sortKey: canonicalize(norm), norm })).sort((a, b) => a.sortKey < b.sortKey ? -1 : a.sortKey > b.sortKey ? 1 : 0).map((x) => x.norm);
|
|
4716
|
+
}
|
|
4699
4717
|
function asStatus(status) {
|
|
4700
4718
|
return status;
|
|
4701
4719
|
}
|
|
@@ -4828,6 +4846,8 @@ var MAX_TOOL_INPUT_BYTES = 64 * 1024;
|
|
|
4828
4846
|
var MAX_PENDING_COUNT = 1e4;
|
|
4829
4847
|
var MAX_PENDING_BYTES = 64 * 1024 * 1024;
|
|
4830
4848
|
var MAX_SENDER_KEYS = 5e4;
|
|
4849
|
+
var MAX_EVIDENCE_ENTRIES = 16;
|
|
4850
|
+
var MAX_EVIDENCE_BYTES = 64 * 1024;
|
|
4831
4851
|
var SWEEP_INTERVAL_MS2 = 3e4;
|
|
4832
4852
|
var GovernanceService = class {
|
|
4833
4853
|
policy;
|
|
@@ -5118,6 +5138,7 @@ var GovernanceService = class {
|
|
|
5118
5138
|
if (callHappened && this.evidenceStore && entry.sessionId) {
|
|
5119
5139
|
this.evidenceStore.recordToolCall(entry.sessionId, entry.toolName, req.status === "success");
|
|
5120
5140
|
}
|
|
5141
|
+
const evidenceOutcomes = this.populateEvidence(req, entry);
|
|
5121
5142
|
const auditId = this.writeAudit({
|
|
5122
5143
|
timestampIso: entry.timestampIso,
|
|
5123
5144
|
origin: entry.origin,
|
|
@@ -5147,7 +5168,62 @@ var GovernanceService = class {
|
|
|
5147
5168
|
finalizedBy: "audit",
|
|
5148
5169
|
expiresAtMs: this.now() + this.ttlMs
|
|
5149
5170
|
});
|
|
5150
|
-
|
|
5171
|
+
const body = { ok: true, audit_record_id: auditId };
|
|
5172
|
+
if (evidenceOutcomes) body["evidence"] = evidenceOutcomes;
|
|
5173
|
+
return { status: 201, body };
|
|
5174
|
+
}
|
|
5175
|
+
/**
|
|
5176
|
+
* Write the optional `/audit` evidence entries for a successful call
|
|
5177
|
+
* (issue #11), returning a per-entry outcome list — or `undefined`
|
|
5178
|
+
* when there is nothing to report (non-success status, or no evidence
|
|
5179
|
+
* supplied). Caps are enforced here, NOT in route validation, so an over-cap
|
|
5180
|
+
* entry soft-drops without discarding the audit row: entries past
|
|
5181
|
+
* `MAX_EVIDENCE_ENTRIES` → `too_many`; oversized `evidence_data` →
|
|
5182
|
+
* `too_large`; no evidence store on the service → `evidence_unavailable`;
|
|
5183
|
+
* a sessionless evaluation → `no_session`; the store's own rejections
|
|
5184
|
+
* (`key_not_in_policy_allowlist`, `closed`) pass through as the per-entry
|
|
5185
|
+
* reason. None of these fail the audit.
|
|
5186
|
+
*/
|
|
5187
|
+
populateEvidence(req, entry) {
|
|
5188
|
+
if (req.status !== "success" || !req.evidence || req.evidence.length === 0) {
|
|
5189
|
+
return void 0;
|
|
5190
|
+
}
|
|
5191
|
+
const outcomes = [];
|
|
5192
|
+
for (let i = 0; i < req.evidence.length; i++) {
|
|
5193
|
+
const e = req.evidence[i];
|
|
5194
|
+
if (!e) continue;
|
|
5195
|
+
if (i >= MAX_EVIDENCE_ENTRIES) {
|
|
5196
|
+
outcomes.push({ evidence_key: e.evidence_key, stored: false, reason: "too_many" });
|
|
5197
|
+
continue;
|
|
5198
|
+
}
|
|
5199
|
+
const bytes = Buffer.byteLength(canonicalize(e.evidence_data ?? null), "utf8");
|
|
5200
|
+
if (bytes > MAX_EVIDENCE_BYTES) {
|
|
5201
|
+
outcomes.push({ evidence_key: e.evidence_key, stored: false, reason: "too_large" });
|
|
5202
|
+
continue;
|
|
5203
|
+
}
|
|
5204
|
+
if (!this.evidenceStore) {
|
|
5205
|
+
outcomes.push({
|
|
5206
|
+
evidence_key: e.evidence_key,
|
|
5207
|
+
stored: false,
|
|
5208
|
+
reason: "evidence_unavailable"
|
|
5209
|
+
});
|
|
5210
|
+
continue;
|
|
5211
|
+
}
|
|
5212
|
+
if (!entry.sessionId) {
|
|
5213
|
+
outcomes.push({ evidence_key: e.evidence_key, stored: false, reason: "no_session" });
|
|
5214
|
+
continue;
|
|
5215
|
+
}
|
|
5216
|
+
const result = this.evidenceStore.putEvidence(entry.sessionId, {
|
|
5217
|
+
evidence_key: e.evidence_key,
|
|
5218
|
+
data: e.evidence_data,
|
|
5219
|
+
tool_name: entry.toolName,
|
|
5220
|
+
ttl_seconds: e.ttl_seconds
|
|
5221
|
+
});
|
|
5222
|
+
outcomes.push(
|
|
5223
|
+
result.stored ? { evidence_key: e.evidence_key, stored: true } : { evidence_key: e.evidence_key, stored: false, reason: result.reason }
|
|
5224
|
+
);
|
|
5225
|
+
}
|
|
5226
|
+
return outcomes;
|
|
5151
5227
|
}
|
|
5152
5228
|
// -------------------------------------------------------------------------
|
|
5153
5229
|
// POST /install-scan — evaluates install-time policy (issue #13)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gethelio/proxy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Open-source MCP governance proxy for AI agents",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"better-sqlite3": "12.8.0",
|
|
62
62
|
"chokidar": "5.0.0",
|
|
63
63
|
"commander": "14.0.3",
|
|
64
|
-
"hono": "4.12.
|
|
64
|
+
"hono": "4.12.26",
|
|
65
65
|
"js-yaml": "4.1.1",
|
|
66
66
|
"picomatch": "4.0.4",
|
|
67
67
|
"safe-regex2": "5.0.0",
|