@revfleet/hscli 0.6.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/CHANGELOG.md +70 -0
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/audit/index.d.ts +3 -0
- package/dist/commands/audit/index.js +226 -0
- package/dist/commands/audit/index.js.map +1 -0
- package/dist/commands/policy/index.d.ts +3 -0
- package/dist/commands/policy/index.js +217 -0
- package/dist/commands/policy/index.js.map +1 -0
- package/dist/core/policy.d.ts +75 -0
- package/dist/core/policy.js +124 -6
- package/dist/core/policy.js.map +1 -1
- package/docs/policy-templates/business-hours.json +21 -0
- package/docs/policy-templates/change-ticket-required.json +35 -0
- package/docs/policy-templates/compliance-strict.json +36 -0
- package/docs/policy-templates/no-deletes.json +17 -0
- package/docs/policy-templates/read-only.json +17 -0
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,75 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.7.0 - 2026-04-21
|
|
4
|
+
|
|
5
|
+
**Trust plane.** New `hscli policy` + `hscli audit` command groups give
|
|
6
|
+
hscli the same operational-trust posture as Salesforce Agent Fabric —
|
|
7
|
+
policy-as-code + audit-over-trace — but in open JSONL + JSON instead
|
|
8
|
+
of a vendor-locked UI. Direct counter to the enterprise moat pillar.
|
|
9
|
+
|
|
10
|
+
### New: hscli policy command group
|
|
11
|
+
|
|
12
|
+
- `hscli policy list` — parse + summarize the active policy file.
|
|
13
|
+
- `hscli policy show-matching <method> <path>` — which rule fires for a
|
|
14
|
+
given request? Use before shipping to verify intent.
|
|
15
|
+
- `hscli policy validate [file]` — syntax + semantic check (invalid
|
|
16
|
+
enums, malformed windows, unnamed rules, etc.).
|
|
17
|
+
- `hscli policy templates list|show|extract` — 5 built-in templates:
|
|
18
|
+
- `read-only` — denies all writes (default action: deny + allow-all-
|
|
19
|
+
reads rule).
|
|
20
|
+
- `business-hours` — writes only 9-17 Mon-Fri in a given timezone.
|
|
21
|
+
- `change-ticket-required` — every write needs `--change-ticket <id>`.
|
|
22
|
+
- `no-deletes` — POST/PATCH/PUT allowed, DELETE always denied.
|
|
23
|
+
- `compliance-strict` — combines the above (business hours + change
|
|
24
|
+
ticket + no deletes + GDPR endpoints require approval).
|
|
25
|
+
|
|
26
|
+
### Enhanced policy schema (v2)
|
|
27
|
+
|
|
28
|
+
Legacy v1 policy files still work. v2 adds:
|
|
29
|
+
- **Glob path matching** — `"path": "**/gdpr-delete**"` matches anywhere.
|
|
30
|
+
`*` matches within a segment, `**` across segments.
|
|
31
|
+
- **Time windows** — `"window": { "tz": "US/Eastern", "hours": "09-17",
|
|
32
|
+
"days": "mon-fri" }`. Enforced in the portal's declared timezone.
|
|
33
|
+
- **`defaultAction`** — `"allow"` (current behavior) or `"deny"` (no-
|
|
34
|
+
rule-match → block). Enables zero-trust policy files.
|
|
35
|
+
- **`requireApproval`** — marks paths as needing out-of-band approval.
|
|
36
|
+
Currently emits `POLICY_APPROVAL_REQUIRED` error; webhook/Slack
|
|
37
|
+
fulfillment lands in v0.7.1.
|
|
38
|
+
- **Rate limit hooks** — `"rateLimit": { "maxPerHour": 10 }` schema
|
|
39
|
+
reserved. Enforcement lands in v0.7.1 alongside approvals.
|
|
40
|
+
|
|
41
|
+
### New: hscli audit command group
|
|
42
|
+
|
|
43
|
+
Reads any trace JSONL (single file or all `~/.revfleet/trace-*.jsonl`)
|
|
44
|
+
and aggregates:
|
|
45
|
+
- `hscli audit timeline` — chronological events, `--since 24h`,
|
|
46
|
+
`--writes-only`, `--limit N`.
|
|
47
|
+
- `hscli audit who <profile>` — breakdown of what a profile did
|
|
48
|
+
(byMethod, byStatus, byPathRoot, last 10).
|
|
49
|
+
- `hscli audit what <path-pattern>` — who touched an endpoint
|
|
50
|
+
(byProfile, byTool — MCP tool names — byMethod, recent writes).
|
|
51
|
+
- `hscli audit writes [--since]` — all write ops, most security-relevant
|
|
52
|
+
view.
|
|
53
|
+
- `hscli audit by-tool` — MCP tool breakdown: calls, writes, errors,
|
|
54
|
+
error rate, avg + max latency. Answers "which agent is chatty/buggy".
|
|
55
|
+
|
|
56
|
+
### Package publishes `docs/policy-templates/`
|
|
57
|
+
|
|
58
|
+
Templates are bundled in the npm tarball so `hscli policy templates
|
|
59
|
+
list` works for any user with just `npm install @revfleet/hscli`.
|
|
60
|
+
|
|
61
|
+
### Validation
|
|
62
|
+
|
|
63
|
+
- 162 tests pass
|
|
64
|
+
- 0 npm audit vulnerabilities
|
|
65
|
+
- Policy enforcement verified end-to-end: `read-only` template
|
|
66
|
+
correctly blocks POST with `POLICY_DEFAULT_DENY` error.
|
|
67
|
+
- Glob matching works (`**/gdpr-delete**`, `/crm/v3/objects/*`).
|
|
68
|
+
- Time-window enforcement works via Intl.DateTimeFormat.
|
|
69
|
+
- Audit timeline/who/what tested on live 3-event trace.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
3
73
|
## 0.6.0 - 2026-04-21
|
|
4
74
|
|
|
5
75
|
**Session tracing + replay.** New `hscli trace` command group brings
|
package/dist/cli.js
CHANGED
|
@@ -15,6 +15,8 @@ import { registerService } from "./commands/service/index.js";
|
|
|
15
15
|
import { registerWebhooks } from "./commands/webhooks/index.js";
|
|
16
16
|
import { registerSeed } from "./commands/seed/index.js";
|
|
17
17
|
import { registerTrace } from "./commands/trace/index.js";
|
|
18
|
+
import { registerPolicy } from "./commands/policy/index.js";
|
|
19
|
+
import { registerAudit } from "./commands/audit/index.js";
|
|
18
20
|
import { registerLists } from "./commands/lists/index.js";
|
|
19
21
|
import { registerSales } from "./commands/sales/index.js";
|
|
20
22
|
import { registerReporting } from "./commands/reporting/index.js";
|
|
@@ -90,6 +92,8 @@ export function createProgram() {
|
|
|
90
92
|
registerApi(program, () => ctx);
|
|
91
93
|
registerSeed(program, () => ctx);
|
|
92
94
|
registerTrace(program, () => ctx);
|
|
95
|
+
registerPolicy(program, () => ctx);
|
|
96
|
+
registerAudit(program, () => ctx);
|
|
93
97
|
registerLists(program, () => ctx);
|
|
94
98
|
registerSales(program, () => ctx);
|
|
95
99
|
registerReporting(program, () => ctx);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { CliError, printResult } from "../../core/output.js";
|
|
5
|
+
function getRevfleetHome() {
|
|
6
|
+
return process.env.HSCLI_HOME?.trim() || join(homedir(), ".revfleet");
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Read all *.jsonl trace files from a given path (file or directory).
|
|
10
|
+
* If no path given, default to scanning ~/.revfleet/ for any trace-*.jsonl.
|
|
11
|
+
*/
|
|
12
|
+
function readAllTraces(fileOrDir) {
|
|
13
|
+
const target = fileOrDir || getRevfleetHome();
|
|
14
|
+
if (!existsSync(target)) {
|
|
15
|
+
throw new CliError("AUDIT_NO_TRACES", `No trace file(s) found at: ${target}. Use \`hscli trace start\` to begin recording.`);
|
|
16
|
+
}
|
|
17
|
+
const stat = statSync(target);
|
|
18
|
+
const files = [];
|
|
19
|
+
if (stat.isDirectory()) {
|
|
20
|
+
for (const f of readdirSync(target)) {
|
|
21
|
+
if (f.startsWith("trace-") && f.endsWith(".jsonl"))
|
|
22
|
+
files.push(join(target, f));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
files.push(target);
|
|
27
|
+
}
|
|
28
|
+
const events = [];
|
|
29
|
+
for (const f of files) {
|
|
30
|
+
for (const line of readFileSync(f, "utf8").split("\n")) {
|
|
31
|
+
const trimmed = line.trim();
|
|
32
|
+
if (!trimmed)
|
|
33
|
+
continue;
|
|
34
|
+
try {
|
|
35
|
+
events.push(JSON.parse(trimmed));
|
|
36
|
+
}
|
|
37
|
+
catch { /* skip */ }
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return events;
|
|
41
|
+
}
|
|
42
|
+
function isWriteEvent(ev) {
|
|
43
|
+
return Boolean(ev.method && ["POST", "PUT", "PATCH", "DELETE"].includes(ev.method));
|
|
44
|
+
}
|
|
45
|
+
function parseSince(spec) {
|
|
46
|
+
// "24h", "7d", "30m" — returns ms before now
|
|
47
|
+
const match = /^(\d+)([mhd])$/.exec(spec.trim());
|
|
48
|
+
if (!match)
|
|
49
|
+
return 0;
|
|
50
|
+
const n = Number(match[1]);
|
|
51
|
+
const unit = match[2];
|
|
52
|
+
const ms = unit === "m" ? 60_000 : unit === "h" ? 3_600_000 : 86_400_000;
|
|
53
|
+
return n * ms;
|
|
54
|
+
}
|
|
55
|
+
function filterBySince(events, since) {
|
|
56
|
+
if (!since)
|
|
57
|
+
return events;
|
|
58
|
+
const cutoffMs = Date.now() - parseSince(since);
|
|
59
|
+
return events.filter(e => {
|
|
60
|
+
if (!e.ts)
|
|
61
|
+
return false;
|
|
62
|
+
return new Date(e.ts).getTime() >= cutoffMs;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
export function registerAudit(program, getCtx) {
|
|
66
|
+
const audit = program.command("audit").description("Operational audit over trace JSONL files. Answers 'who did what when' across every hscli / MCP request. Reads from a specific file or auto-scans ~/.revfleet/ for all recorded sessions.");
|
|
67
|
+
audit
|
|
68
|
+
.command("timeline")
|
|
69
|
+
.description("Chronological event list across traces. Default: last 100 events from ~/.revfleet/*.jsonl.")
|
|
70
|
+
.argument("[file-or-dir]", "Path to a trace file or directory (default: ~/.revfleet/)")
|
|
71
|
+
.option("--since <spec>", "Only events in the last window: 15m, 24h, 7d")
|
|
72
|
+
.option("--limit <n>", "Max events to show", "100")
|
|
73
|
+
.option("--writes-only", "Only POST/PUT/PATCH/DELETE events")
|
|
74
|
+
.action(async (fileOrDir, opts) => {
|
|
75
|
+
const ctx = getCtx();
|
|
76
|
+
const all = readAllTraces(fileOrDir);
|
|
77
|
+
let events = filterBySince(all, opts.since);
|
|
78
|
+
if (opts.writesOnly)
|
|
79
|
+
events = events.filter(isWriteEvent);
|
|
80
|
+
events.sort((a, b) => (a.ts ?? "").localeCompare(b.ts ?? ""));
|
|
81
|
+
const limit = Number(opts.limit) || 100;
|
|
82
|
+
printResult(ctx, {
|
|
83
|
+
totalLoaded: all.length,
|
|
84
|
+
afterFilters: events.length,
|
|
85
|
+
showing: Math.min(events.length, limit),
|
|
86
|
+
filters: {
|
|
87
|
+
since: opts.since ?? "(none)",
|
|
88
|
+
writesOnly: Boolean(opts.writesOnly),
|
|
89
|
+
},
|
|
90
|
+
events: events.slice(-limit),
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
audit
|
|
94
|
+
.command("who")
|
|
95
|
+
.description("What has a given profile done? Reads across all traces and breaks down by method/path/status.")
|
|
96
|
+
.argument("<profile>", "Profile name to audit")
|
|
97
|
+
.option("--since <spec>", "Window: 15m, 24h, 7d")
|
|
98
|
+
.option("--file <path>", "Single trace file (default: scan ~/.revfleet/)")
|
|
99
|
+
.action(async (profile, opts) => {
|
|
100
|
+
const ctx = getCtx();
|
|
101
|
+
const events = filterBySince(readAllTraces(opts.file), opts.since).filter(e => e.profile === profile);
|
|
102
|
+
const byMethod = {};
|
|
103
|
+
const byStatus = {};
|
|
104
|
+
const byPathRoot = {};
|
|
105
|
+
for (const e of events) {
|
|
106
|
+
byMethod[e.method ?? "?"] = (byMethod[e.method ?? "?"] || 0) + 1;
|
|
107
|
+
byStatus[String(e.status ?? "err")] = (byStatus[String(e.status ?? "err")] || 0) + 1;
|
|
108
|
+
const root = (e.path ?? "").split("/").filter(Boolean)[0] || "?";
|
|
109
|
+
byPathRoot[root] = (byPathRoot[root] || 0) + 1;
|
|
110
|
+
}
|
|
111
|
+
const writes = events.filter(isWriteEvent);
|
|
112
|
+
printResult(ctx, {
|
|
113
|
+
profile,
|
|
114
|
+
since: opts.since ?? "(all time)",
|
|
115
|
+
totalEvents: events.length,
|
|
116
|
+
reads: events.length - writes.length,
|
|
117
|
+
writes: writes.length,
|
|
118
|
+
byMethod,
|
|
119
|
+
byStatus,
|
|
120
|
+
byPathRoot,
|
|
121
|
+
lastTen: events.slice(-10).map(e => ({ ts: e.ts, method: e.method, path: e.path, status: e.status })),
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
audit
|
|
125
|
+
.command("what")
|
|
126
|
+
.description("Who touched a given path? Reads across traces, buckets by profile + toolName.")
|
|
127
|
+
.argument("<path-pattern>", "Substring or full path (e.g. '/crm/v3/objects/contacts')")
|
|
128
|
+
.option("--since <spec>", "Window: 15m, 24h, 7d")
|
|
129
|
+
.option("--file <path>", "Single trace file")
|
|
130
|
+
.action(async (pathPattern, opts) => {
|
|
131
|
+
const ctx = getCtx();
|
|
132
|
+
const events = filterBySince(readAllTraces(opts.file), opts.since)
|
|
133
|
+
.filter(e => (e.path ?? "").includes(pathPattern));
|
|
134
|
+
const byProfile = {};
|
|
135
|
+
const byTool = {};
|
|
136
|
+
const byMethod = {};
|
|
137
|
+
for (const e of events) {
|
|
138
|
+
byProfile[e.profile ?? "?"] = (byProfile[e.profile ?? "?"] || 0) + 1;
|
|
139
|
+
if (e.toolName)
|
|
140
|
+
byTool[e.toolName] = (byTool[e.toolName] || 0) + 1;
|
|
141
|
+
byMethod[e.method ?? "?"] = (byMethod[e.method ?? "?"] || 0) + 1;
|
|
142
|
+
}
|
|
143
|
+
const writes = events.filter(isWriteEvent);
|
|
144
|
+
printResult(ctx, {
|
|
145
|
+
pathPattern,
|
|
146
|
+
since: opts.since ?? "(all time)",
|
|
147
|
+
totalHits: events.length,
|
|
148
|
+
reads: events.length - writes.length,
|
|
149
|
+
writes: writes.length,
|
|
150
|
+
byProfile,
|
|
151
|
+
byTool,
|
|
152
|
+
byMethod,
|
|
153
|
+
recentWrites: writes.slice(-10).map(e => ({ ts: e.ts, profile: e.profile, toolName: e.toolName, method: e.method, path: e.path, status: e.status })),
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
audit
|
|
157
|
+
.command("writes")
|
|
158
|
+
.description("All write operations across traces — the most security-relevant audit view.")
|
|
159
|
+
.option("--since <spec>", "Window: 15m, 24h, 7d")
|
|
160
|
+
.option("--file <path>", "Single trace file")
|
|
161
|
+
.option("--limit <n>", "Max writes to show", "100")
|
|
162
|
+
.action(async (opts) => {
|
|
163
|
+
const ctx = getCtx();
|
|
164
|
+
const events = filterBySince(readAllTraces(opts.file), opts.since).filter(isWriteEvent);
|
|
165
|
+
events.sort((a, b) => (a.ts ?? "").localeCompare(b.ts ?? ""));
|
|
166
|
+
const limit = Number(opts.limit) || 100;
|
|
167
|
+
const failed = events.filter(e => e.error || (e.status !== undefined && e.status >= 400));
|
|
168
|
+
printResult(ctx, {
|
|
169
|
+
since: opts.since ?? "(all time)",
|
|
170
|
+
totalWrites: events.length,
|
|
171
|
+
successfulWrites: events.length - failed.length,
|
|
172
|
+
failedWrites: failed.length,
|
|
173
|
+
showing: Math.min(events.length, limit),
|
|
174
|
+
writes: events.slice(-limit).map(e => ({
|
|
175
|
+
ts: e.ts,
|
|
176
|
+
profile: e.profile,
|
|
177
|
+
toolName: e.toolName,
|
|
178
|
+
method: e.method,
|
|
179
|
+
path: e.path,
|
|
180
|
+
status: e.status,
|
|
181
|
+
durationMs: e.durationMs,
|
|
182
|
+
})),
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
audit
|
|
186
|
+
.command("by-tool")
|
|
187
|
+
.description("Breakdown per MCP tool: which tool wrote how much, error rate, avg latency. Answers 'which agent is chatty/buggy'.")
|
|
188
|
+
.option("--since <spec>", "Window: 15m, 24h, 7d")
|
|
189
|
+
.option("--file <path>", "Single trace file")
|
|
190
|
+
.action(async (opts) => {
|
|
191
|
+
const ctx = getCtx();
|
|
192
|
+
const events = filterBySince(readAllTraces(opts.file), opts.since).filter(e => e.toolName);
|
|
193
|
+
const byTool = new Map();
|
|
194
|
+
for (const e of events) {
|
|
195
|
+
const k = e.toolName;
|
|
196
|
+
if (!byTool.has(k))
|
|
197
|
+
byTool.set(k, { calls: 0, writes: 0, errors: 0, totalMs: 0, maxMs: 0 });
|
|
198
|
+
const stats = byTool.get(k);
|
|
199
|
+
stats.calls++;
|
|
200
|
+
if (isWriteEvent(e))
|
|
201
|
+
stats.writes++;
|
|
202
|
+
if (e.error || (e.status !== undefined && e.status >= 400))
|
|
203
|
+
stats.errors++;
|
|
204
|
+
stats.totalMs += e.durationMs ?? 0;
|
|
205
|
+
stats.maxMs = Math.max(stats.maxMs, e.durationMs ?? 0);
|
|
206
|
+
}
|
|
207
|
+
const breakdown = [...byTool.entries()]
|
|
208
|
+
.map(([tool, s]) => ({
|
|
209
|
+
tool,
|
|
210
|
+
calls: s.calls,
|
|
211
|
+
writes: s.writes,
|
|
212
|
+
errors: s.errors,
|
|
213
|
+
errorRate: s.calls > 0 ? Math.round((s.errors / s.calls) * 1000) / 10 + "%" : "0%",
|
|
214
|
+
avgMs: Math.round(s.totalMs / s.calls),
|
|
215
|
+
maxMs: s.maxMs,
|
|
216
|
+
}))
|
|
217
|
+
.sort((a, b) => b.calls - a.calls);
|
|
218
|
+
printResult(ctx, {
|
|
219
|
+
since: opts.since ?? "(all time)",
|
|
220
|
+
totalMcpCalls: events.length,
|
|
221
|
+
uniqueTools: breakdown.length,
|
|
222
|
+
breakdown,
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/audit/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, existsSync, readdirSync, mkdirSync } from "node:fs";
|
|
2
|
+
import { dirname, join, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { CliError, printResult } from "../../core/output.js";
|
|
5
|
+
import { readPolicyFile, findMatchingRule } from "../../core/policy.js";
|
|
6
|
+
function getTemplatesDir() {
|
|
7
|
+
// Templates ship alongside the built dist/. When running via `hscli` binary,
|
|
8
|
+
// we need to walk up from the module's dist location to find the docs/ dir.
|
|
9
|
+
// This only matters for installed npm package — in dev mode tsc outputs
|
|
10
|
+
// into dist/ and the docs/ dir is at the repo root.
|
|
11
|
+
const thisFile = fileURLToPath(import.meta.url);
|
|
12
|
+
// dist/commands/policy/index.js → repo root
|
|
13
|
+
const candidates = [
|
|
14
|
+
resolve(dirname(thisFile), "../../../docs/policy-templates"),
|
|
15
|
+
resolve(dirname(thisFile), "../../../../docs/policy-templates"),
|
|
16
|
+
resolve(dirname(thisFile), "../../docs/policy-templates"),
|
|
17
|
+
];
|
|
18
|
+
for (const candidate of candidates) {
|
|
19
|
+
if (existsSync(candidate))
|
|
20
|
+
return candidate;
|
|
21
|
+
}
|
|
22
|
+
// Last resort — this will only fail at runtime if templates are missing
|
|
23
|
+
return resolve(dirname(thisFile), "../../../docs/policy-templates");
|
|
24
|
+
}
|
|
25
|
+
function getPolicyPath(ctx) {
|
|
26
|
+
return ctx.policyFile?.trim() || process.env.HSCLI_POLICY_FILE?.trim();
|
|
27
|
+
}
|
|
28
|
+
export function registerPolicy(program, getCtx) {
|
|
29
|
+
const policy = program.command("policy").description("Manage policy-as-code: audit the active policy, list/extract built-in templates, validate your own files.");
|
|
30
|
+
policy
|
|
31
|
+
.command("list")
|
|
32
|
+
.description("Show the active policy (from --policy-file or HSCLI_POLICY_FILE). Parses + summarizes all rules by profile.")
|
|
33
|
+
.action(async () => {
|
|
34
|
+
const ctx = getCtx();
|
|
35
|
+
const path = getPolicyPath(ctx);
|
|
36
|
+
if (!path) {
|
|
37
|
+
printResult(ctx, {
|
|
38
|
+
active: false,
|
|
39
|
+
message: "No policy file set. Pass --policy-file <path> or set HSCLI_POLICY_FILE env var.",
|
|
40
|
+
suggestions: [
|
|
41
|
+
"hscli policy templates # list built-in templates",
|
|
42
|
+
"hscli policy templates extract read-only --to ./policy.json",
|
|
43
|
+
],
|
|
44
|
+
});
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const config = readPolicyFile(path);
|
|
48
|
+
const summary = {
|
|
49
|
+
active: true,
|
|
50
|
+
file: path,
|
|
51
|
+
version: config.version ?? 1,
|
|
52
|
+
profiles: Object.fromEntries(Object.entries(config.profiles ?? {}).map(([name, cfg]) => [
|
|
53
|
+
name,
|
|
54
|
+
{
|
|
55
|
+
defaultAction: cfg.defaultAction ?? "allow",
|
|
56
|
+
ruleCount: cfg.rules?.length ?? 0,
|
|
57
|
+
ruleNames: (cfg.rules ?? []).map(r => r.name || "(unnamed)"),
|
|
58
|
+
legacyFlags: {
|
|
59
|
+
allowWrite: cfg.allowWrite,
|
|
60
|
+
allowDelete: cfg.allowDelete,
|
|
61
|
+
requireChangeTicket: cfg.requireChangeTicket,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
])),
|
|
65
|
+
hasDefaults: Boolean(config.defaults),
|
|
66
|
+
blockedPrefixes: config.blockedMethodPathPrefixes,
|
|
67
|
+
};
|
|
68
|
+
printResult(ctx, summary);
|
|
69
|
+
});
|
|
70
|
+
policy
|
|
71
|
+
.command("show-matching")
|
|
72
|
+
.description("Print which policy rule (if any) would be applied to a hypothetical request. Useful for verifying rules before shipping.")
|
|
73
|
+
.argument("<method>", "HTTP method: GET, POST, PATCH, PUT, DELETE")
|
|
74
|
+
.argument("<path>", "Request path (e.g. /crm/v3/objects/contacts/123)")
|
|
75
|
+
.option("--profile <name>", "Profile to evaluate against (defaults to the current --profile)")
|
|
76
|
+
.action(async (method, requestPath, opts) => {
|
|
77
|
+
const ctx = getCtx();
|
|
78
|
+
const policyPath = getPolicyPath(ctx);
|
|
79
|
+
if (!policyPath) {
|
|
80
|
+
throw new CliError("NO_POLICY_FILE", "No policy file configured. Pass --policy-file or set HSCLI_POLICY_FILE.");
|
|
81
|
+
}
|
|
82
|
+
const config = readPolicyFile(policyPath);
|
|
83
|
+
const profile = opts.profile || ctx.profile;
|
|
84
|
+
const profileConfig = config.profiles?.[profile] ?? config.defaults ?? {};
|
|
85
|
+
const matched = findMatchingRule(profileConfig, method, requestPath);
|
|
86
|
+
if (matched) {
|
|
87
|
+
printResult(ctx, {
|
|
88
|
+
profile,
|
|
89
|
+
request: { method, path: requestPath },
|
|
90
|
+
matchedRule: matched,
|
|
91
|
+
effectiveAction: matched.action ?? "allow",
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
printResult(ctx, {
|
|
96
|
+
profile,
|
|
97
|
+
request: { method, path: requestPath },
|
|
98
|
+
matchedRule: null,
|
|
99
|
+
effectiveAction: profileConfig.defaultAction ?? "allow",
|
|
100
|
+
note: "No rule matched. Falling back to the profile's defaultAction.",
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
policy
|
|
105
|
+
.command("validate")
|
|
106
|
+
.description("Parse + semantic-check a policy file without enforcing it.")
|
|
107
|
+
.argument("[file]", "Policy file path (default: the active --policy-file / HSCLI_POLICY_FILE)")
|
|
108
|
+
.action(async (fileArg) => {
|
|
109
|
+
const ctx = getCtx();
|
|
110
|
+
const path = fileArg || getPolicyPath(ctx);
|
|
111
|
+
if (!path) {
|
|
112
|
+
throw new CliError("NO_POLICY_FILE", "No file passed and no active policy configured.");
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
const config = readPolicyFile(path);
|
|
116
|
+
const issues = [];
|
|
117
|
+
const warnings = [];
|
|
118
|
+
for (const [profileName, cfg] of Object.entries(config.profiles ?? {})) {
|
|
119
|
+
for (const rule of cfg.rules ?? []) {
|
|
120
|
+
if (!rule.match)
|
|
121
|
+
warnings.push(`[${profileName}] rule '${rule.name ?? "(unnamed)"}' has no match criteria — will match everything`);
|
|
122
|
+
if (rule.action && rule.action !== "allow" && rule.action !== "deny")
|
|
123
|
+
issues.push(`[${profileName}] rule '${rule.name ?? "(unnamed)"}' has invalid action '${rule.action}' (must be 'allow' or 'deny')`);
|
|
124
|
+
if (rule.window?.days && !/^[a-z]{3}(-[a-z]{3}|(,[a-z]{3})*)$/i.test(rule.window.days.trim())) {
|
|
125
|
+
warnings.push(`[${profileName}] rule '${rule.name ?? "(unnamed)"}' has non-standard window.days syntax: '${rule.window.days}'`);
|
|
126
|
+
}
|
|
127
|
+
if (rule.window?.hours && !/^\d{1,2}-\d{1,2}$/.test(rule.window.hours)) {
|
|
128
|
+
issues.push(`[${profileName}] rule '${rule.name ?? "(unnamed)"}' has invalid window.hours: '${rule.window.hours}' (must be 'HH-HH' 24h format)`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
printResult(ctx, {
|
|
133
|
+
valid: issues.length === 0,
|
|
134
|
+
file: path,
|
|
135
|
+
version: config.version ?? 1,
|
|
136
|
+
profileCount: Object.keys(config.profiles ?? {}).length,
|
|
137
|
+
totalRules: Object.values(config.profiles ?? {}).reduce((s, c) => s + (c.rules?.length ?? 0), 0),
|
|
138
|
+
issues,
|
|
139
|
+
warnings,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
if (err instanceof CliError)
|
|
144
|
+
throw err;
|
|
145
|
+
throw new CliError("POLICY_PARSE_ERROR", err instanceof Error ? err.message : String(err));
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
const templates = policy.command("templates").description("Built-in policy templates for common trust scenarios");
|
|
149
|
+
templates
|
|
150
|
+
.command("list")
|
|
151
|
+
.description("List available built-in policy templates")
|
|
152
|
+
.action(async () => {
|
|
153
|
+
const ctx = getCtx();
|
|
154
|
+
const dir = getTemplatesDir();
|
|
155
|
+
if (!existsSync(dir)) {
|
|
156
|
+
throw new CliError("TEMPLATES_DIR_MISSING", `Template directory not found: ${dir}`);
|
|
157
|
+
}
|
|
158
|
+
const files = readdirSync(dir).filter(f => f.endsWith(".json"));
|
|
159
|
+
const templatesWithMeta = files.map(f => {
|
|
160
|
+
try {
|
|
161
|
+
const content = JSON.parse(readFileSync(join(dir, f), "utf8"));
|
|
162
|
+
return { name: f.replace(/\.json$/, ""), version: content.version, description: content.description ?? "(no description)" };
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return { name: f.replace(/\.json$/, ""), version: undefined, description: "(failed to parse)" };
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
printResult(ctx, {
|
|
169
|
+
count: templatesWithMeta.length,
|
|
170
|
+
templates: templatesWithMeta,
|
|
171
|
+
note: "Use `hscli policy templates show <name>` to view; `hscli policy templates extract <name> --to <file>` to copy.",
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
templates
|
|
175
|
+
.command("show")
|
|
176
|
+
.description("Print a template's content")
|
|
177
|
+
.argument("<name>", "Template name (from `hscli policy templates list`)")
|
|
178
|
+
.action(async (name) => {
|
|
179
|
+
const ctx = getCtx();
|
|
180
|
+
const path = join(getTemplatesDir(), `${name}.json`);
|
|
181
|
+
if (!existsSync(path)) {
|
|
182
|
+
throw new CliError("TEMPLATE_NOT_FOUND", `Template '${name}' not found. Available: ${readdirSync(getTemplatesDir()).filter(f => f.endsWith(".json")).map(f => f.replace(/\.json$/, "")).join(", ")}`);
|
|
183
|
+
}
|
|
184
|
+
const content = JSON.parse(readFileSync(path, "utf8"));
|
|
185
|
+
printResult(ctx, content);
|
|
186
|
+
});
|
|
187
|
+
templates
|
|
188
|
+
.command("extract")
|
|
189
|
+
.description("Copy a built-in template to a local file for editing")
|
|
190
|
+
.argument("<name>", "Template name")
|
|
191
|
+
.requiredOption("--to <file>", "Destination file path")
|
|
192
|
+
.action(async (name, opts) => {
|
|
193
|
+
const ctx = getCtx();
|
|
194
|
+
const srcPath = join(getTemplatesDir(), `${name}.json`);
|
|
195
|
+
if (!existsSync(srcPath)) {
|
|
196
|
+
throw new CliError("TEMPLATE_NOT_FOUND", `Template '${name}' not found.`);
|
|
197
|
+
}
|
|
198
|
+
const dest = String(opts.to);
|
|
199
|
+
if (existsSync(dest)) {
|
|
200
|
+
throw new CliError("DEST_FILE_EXISTS", `Destination file already exists: ${dest}. Delete it first or choose another path.`);
|
|
201
|
+
}
|
|
202
|
+
mkdirSync(dirname(dest), { recursive: true });
|
|
203
|
+
const content = readFileSync(srcPath, "utf8");
|
|
204
|
+
writeFileSync(dest, content, { encoding: "utf8", mode: 0o644 });
|
|
205
|
+
printResult(ctx, {
|
|
206
|
+
extracted: true,
|
|
207
|
+
from: srcPath,
|
|
208
|
+
to: dest,
|
|
209
|
+
nextSteps: [
|
|
210
|
+
`hscli policy validate ${dest}`,
|
|
211
|
+
`hscli --policy-file ${dest} crm contacts list`,
|
|
212
|
+
`export HSCLI_POLICY_FILE=${dest}`,
|
|
213
|
+
],
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/policy/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC1F,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExE,SAAS,eAAe;IACtB,6EAA6E;IAC7E,4EAA4E;IAC5E,wEAAwE;IACxE,oDAAoD;IACpD,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChD,4CAA4C;IAC5C,MAAM,UAAU,GAAG;QACjB,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,gCAAgC,CAAC;QAC5D,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,mCAAmC,CAAC;QAC/D,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,6BAA6B,CAAC;KAC1D,CAAC;IACF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;IAC9C,CAAC;IACD,wEAAwE;IACxE,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,gCAAgC,CAAC,CAAC;AACtE,CAAC;AAED,SAAS,aAAa,CAAC,GAAe;IACpC,OAAO,GAAG,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAgB,EAAE,MAAwB;IACvE,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,2GAA2G,CAAC,CAAC;IAElK,MAAM;SACH,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,6GAA6G,CAAC;SAC1H,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,WAAW,CAAC,GAAG,EAAE;gBACf,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,iFAAiF;gBAC1F,WAAW,EAAE;oBACX,0DAA0D;oBAC1D,6DAA6D;iBAC9D;aACF,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,OAAO,GAAG;YACd,MAAM,EAAE,IAAI;YACZ,IAAI,EAAE,IAAI;YACV,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,CAAC;YAC5B,QAAQ,EAAE,MAAM,CAAC,WAAW,CAC1B,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;gBACzD,IAAI;gBACJ;oBACE,aAAa,EAAE,GAAG,CAAC,aAAa,IAAI,OAAO;oBAC3C,SAAS,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC;oBACjC,SAAS,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,WAAW,CAAC;oBAC5D,WAAW,EAAE;wBACX,UAAU,EAAE,GAAG,CAAC,UAAU;wBAC1B,WAAW,EAAE,GAAG,CAAC,WAAW;wBAC5B,mBAAmB,EAAE,GAAG,CAAC,mBAAmB;qBAC7C;iBACF;aACF,CAAC,CACH;YACD,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;YACrC,eAAe,EAAE,MAAM,CAAC,yBAAyB;SAClD,CAAC;QACF,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEL,MAAM;SACH,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,0HAA0H,CAAC;SACvI,QAAQ,CAAC,UAAU,EAAE,4CAA4C,CAAC;SAClE,QAAQ,CAAC,QAAQ,EAAE,kDAAkD,CAAC;SACtE,MAAM,CAAC,kBAAkB,EAAE,iEAAiE,CAAC;SAC7F,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE;QAC1C,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;QACrB,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;QACtC,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,QAAQ,CAAC,gBAAgB,EAAE,yEAAyE,CAAC,CAAC;QAClH,CAAC;QACD,MAAM,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC;QAC5C,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;QAC1E,MAAM,OAAO,GAAG,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;QACrE,IAAI,OAAO,EAAE,CAAC;YACZ,WAAW,CAAC,GAAG,EAAE;gBACf,OAAO;gBACP,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE;gBACtC,WAAW,EAAE,OAAO;gBACpB,eAAe,EAAE,OAAO,CAAC,MAAM,IAAI,OAAO;aAC3C,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,GAAG,EAAE;gBACf,OAAO;gBACP,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE;gBACtC,WAAW,EAAE,IAAI;gBACjB,eAAe,EAAE,aAAa,CAAC,aAAa,IAAI,OAAO;gBACvD,IAAI,EAAE,+DAA+D;aACtE,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,MAAM;SACH,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,4DAA4D,CAAC;SACzE,QAAQ,CAAC,QAAQ,EAAE,0EAA0E,CAAC;SAC9F,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACxB,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,OAAO,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,QAAQ,CAAC,gBAAgB,EAAE,iDAAiD,CAAC,CAAC;QAC1F,CAAC;QACD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,MAAM,GAAa,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAa,EAAE,CAAC;YAE9B,KAAK,MAAM,CAAC,WAAW,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,CAAC;gBACvE,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;oBACnC,IAAI,CAAC,IAAI,CAAC,KAAK;wBAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,WAAW,WAAW,IAAI,CAAC,IAAI,IAAI,WAAW,iDAAiD,CAAC,CAAC;oBACpI,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM;wBAAE,MAAM,CAAC,IAAI,CAAC,IAAI,WAAW,WAAW,IAAI,CAAC,IAAI,IAAI,WAAW,yBAAyB,IAAI,CAAC,MAAM,+BAA+B,CAAC,CAAC;oBACzM,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,qCAAqC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;wBAC9F,QAAQ,CAAC,IAAI,CAAC,IAAI,WAAW,WAAW,IAAI,CAAC,IAAI,IAAI,WAAW,2CAA2C,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;oBAClI,CAAC;oBACD,IAAI,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;wBACvE,MAAM,CAAC,IAAI,CAAC,IAAI,WAAW,WAAW,IAAI,CAAC,IAAI,IAAI,WAAW,gCAAgC,IAAI,CAAC,MAAM,CAAC,KAAK,gCAAgC,CAAC,CAAC;oBACnJ,CAAC;gBACH,CAAC;YACH,CAAC;YAED,WAAW,CAAC,GAAG,EAAE;gBACf,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;gBAC1B,IAAI,EAAE,IAAI;gBACV,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,CAAC;gBAC5B,YAAY,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,MAAM;gBACvD,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;gBAChG,MAAM;gBACN,QAAQ;aACT,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,QAAQ;gBAAE,MAAM,GAAG,CAAC;YACvC,MAAM,IAAI,QAAQ,CAAC,oBAAoB,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7F,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,sDAAsD,CAAC,CAAC;IAElH,SAAS;SACN,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,0CAA0C,CAAC;SACvD,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;QACrB,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;QAC9B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,QAAQ,CAAC,uBAAuB,EAAE,iCAAiC,GAAG,EAAE,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;QAChE,MAAM,iBAAiB,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;YACtC,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAA+C,CAAC;gBAC7G,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,kBAAkB,EAAE,CAAC;YAC9H,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,mBAAmB,EAAE,CAAC;YAClG,CAAC;QACH,CAAC,CAAC,CAAC;QACH,WAAW,CAAC,GAAG,EAAE;YACf,KAAK,EAAE,iBAAiB,CAAC,MAAM;YAC/B,SAAS,EAAE,iBAAiB;YAC5B,IAAI,EAAE,gHAAgH;SACvH,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEL,SAAS;SACN,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,4BAA4B,CAAC;SACzC,QAAQ,CAAC,QAAQ,EAAE,oDAAoD,CAAC;SACxE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,EAAE,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;QACrD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,MAAM,IAAI,QAAQ,CAAC,oBAAoB,EAAE,aAAa,IAAI,2BAA2B,WAAW,CAAC,eAAe,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxM,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QACvD,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEL,SAAS;SACN,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,sDAAsD,CAAC;SACnE,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;SACnC,cAAc,CAAC,aAAa,EAAE,uBAAuB,CAAC;SACtD,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;QAC3B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;QACrB,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;QACxD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,QAAQ,CAAC,oBAAoB,EAAE,aAAa,IAAI,cAAc,CAAC,CAAC;QAC5E,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7B,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,QAAQ,CAAC,kBAAkB,EAAE,oCAAoC,IAAI,2CAA2C,CAAC,CAAC;QAC9H,CAAC;QACD,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC9C,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAChE,WAAW,CAAC,GAAG,EAAE;YACf,SAAS,EAAE,IAAI;YACf,IAAI,EAAE,OAAO;YACb,EAAE,EAAE,IAAI;YACR,SAAS,EAAE;gBACT,yBAAyB,IAAI,EAAE;gBAC/B,uBAAuB,IAAI,oBAAoB;gBAC/C,4BAA4B,IAAI,EAAE;aACnC;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
|
package/dist/core/policy.d.ts
CHANGED
|
@@ -1,2 +1,77 @@
|
|
|
1
1
|
import type { CliContext } from "./output.js";
|
|
2
|
+
/**
|
|
3
|
+
* Policy-as-code for HSCLI writes.
|
|
4
|
+
*
|
|
5
|
+
* Two supported policy formats:
|
|
6
|
+
*
|
|
7
|
+
* 1. LEGACY (v0.1-v0.6) — flat JSON with `defaults`, `profiles`, and
|
|
8
|
+
* `blockedMethodPathPrefixes`. Still supported for backward compat.
|
|
9
|
+
*
|
|
10
|
+
* 2. v0.7+ — structured rules with glob patterns, time windows, and
|
|
11
|
+
* approval requirements. Shape:
|
|
12
|
+
*
|
|
13
|
+
* {
|
|
14
|
+
* "version": 2,
|
|
15
|
+
* "profiles": {
|
|
16
|
+
* "<profile-name>": {
|
|
17
|
+
* "defaultAction": "allow" | "deny",
|
|
18
|
+
* "rules": [
|
|
19
|
+
* {
|
|
20
|
+
* "match": { "method": "DELETE", "path": "/crm/v3/objects/*" },
|
|
21
|
+
* "action": "allow" | "deny",
|
|
22
|
+
* "requireChangeTicket": true,
|
|
23
|
+
* "requireApproval": "webhook:<url>" | "manual" | null,
|
|
24
|
+
* "rateLimit": { "maxPerHour": 10 },
|
|
25
|
+
* "window": { "tz": "US/Eastern", "hours": "09-17", "days": "mon-fri" }
|
|
26
|
+
* }
|
|
27
|
+
* ]
|
|
28
|
+
* }
|
|
29
|
+
* }
|
|
30
|
+
* }
|
|
31
|
+
*
|
|
32
|
+
* Rule evaluation: first match wins. If no rule matches, use `defaultAction`
|
|
33
|
+
* (or fall back to the legacy flat field `allowWrite` for v1 files).
|
|
34
|
+
*/
|
|
35
|
+
export interface PolicyRuleMatch {
|
|
36
|
+
method?: "POST" | "PATCH" | "PUT" | "DELETE" | "*";
|
|
37
|
+
path?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface PolicyWindow {
|
|
40
|
+
tz?: string;
|
|
41
|
+
hours?: string;
|
|
42
|
+
days?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface PolicyRateLimit {
|
|
45
|
+
maxPerHour?: number;
|
|
46
|
+
}
|
|
47
|
+
export interface PolicyRule {
|
|
48
|
+
name?: string;
|
|
49
|
+
match?: PolicyRuleMatch;
|
|
50
|
+
action?: "allow" | "deny";
|
|
51
|
+
requireChangeTicket?: boolean;
|
|
52
|
+
requireApproval?: string | null;
|
|
53
|
+
rateLimit?: PolicyRateLimit;
|
|
54
|
+
window?: PolicyWindow;
|
|
55
|
+
allowWrite?: boolean;
|
|
56
|
+
allowDelete?: boolean;
|
|
57
|
+
}
|
|
58
|
+
export interface PolicyProfileConfig {
|
|
59
|
+
defaultAction?: "allow" | "deny";
|
|
60
|
+
rules?: PolicyRule[];
|
|
61
|
+
allowWrite?: boolean;
|
|
62
|
+
allowDelete?: boolean;
|
|
63
|
+
requireChangeTicket?: boolean;
|
|
64
|
+
}
|
|
65
|
+
export interface PolicyConfig {
|
|
66
|
+
version?: 1 | 2;
|
|
67
|
+
defaults?: PolicyProfileConfig;
|
|
68
|
+
profiles?: Record<string, PolicyProfileConfig>;
|
|
69
|
+
blockedMethodPathPrefixes?: Record<string, string[]>;
|
|
70
|
+
}
|
|
71
|
+
export declare function readPolicyFile(path: string): PolicyConfig;
|
|
72
|
+
/**
|
|
73
|
+
* Find the first matching rule for a (method, path) pair in a profile config.
|
|
74
|
+
* Returns null if no rule matches. Supports both v1 and v2 shapes.
|
|
75
|
+
*/
|
|
76
|
+
export declare function findMatchingRule(profileConfig: PolicyProfileConfig, method: string, path: string): PolicyRule | null;
|
|
2
77
|
export declare function enforceWritePolicy(ctx: CliContext, method: "POST" | "PATCH" | "PUT" | "DELETE", path: string): void;
|
package/dist/core/policy.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { CliError } from "./output.js";
|
|
3
|
-
function readPolicyFile(path) {
|
|
3
|
+
export function readPolicyFile(path) {
|
|
4
4
|
if (!existsSync(path)) {
|
|
5
5
|
throw new CliError("POLICY_FILE_NOT_FOUND", `Policy file not found: ${path}`);
|
|
6
6
|
}
|
|
@@ -11,23 +11,141 @@ function readPolicyFile(path) {
|
|
|
11
11
|
throw new CliError("POLICY_INVALID_JSON", `Invalid policy JSON: ${path}`);
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
+
/** Convert a glob pattern to a regex. `*` matches path segment (no `/`), `**` matches across segments. */
|
|
15
|
+
function globToRegex(pattern) {
|
|
16
|
+
// Escape regex special chars except * and /
|
|
17
|
+
let re = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
|
|
18
|
+
// ** matches any (including /)
|
|
19
|
+
re = re.replace(/\*\*/g, "__GLOBSTAR__");
|
|
20
|
+
// * matches anything except /
|
|
21
|
+
re = re.replace(/\*/g, "[^/]*");
|
|
22
|
+
re = re.replace(/__GLOBSTAR__/g, ".*");
|
|
23
|
+
return new RegExp("^" + re + "$");
|
|
24
|
+
}
|
|
25
|
+
function methodMatches(ruleMethod, requestMethod) {
|
|
26
|
+
if (!ruleMethod || ruleMethod === "*")
|
|
27
|
+
return true;
|
|
28
|
+
return ruleMethod.toUpperCase() === requestMethod.toUpperCase();
|
|
29
|
+
}
|
|
30
|
+
function pathMatches(rulePath, requestPath) {
|
|
31
|
+
if (!rulePath || rulePath === "*" || rulePath === "**")
|
|
32
|
+
return true;
|
|
33
|
+
return globToRegex(rulePath).test(requestPath);
|
|
34
|
+
}
|
|
35
|
+
function isWithinWindow(window) {
|
|
36
|
+
if (!window)
|
|
37
|
+
return true;
|
|
38
|
+
const now = new Date();
|
|
39
|
+
// Days
|
|
40
|
+
if (window.days) {
|
|
41
|
+
const dayNames = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
|
|
42
|
+
const today = dayNames[now.getUTCDay()];
|
|
43
|
+
const allowed = parseDays(window.days);
|
|
44
|
+
if (!allowed.includes(today))
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
// Hours (interpret in window.tz if given, else local)
|
|
48
|
+
if (window.hours) {
|
|
49
|
+
const [fromStr, toStr] = window.hours.split("-");
|
|
50
|
+
const fromHour = Number(fromStr);
|
|
51
|
+
const toHour = Number(toStr);
|
|
52
|
+
const tz = window.tz;
|
|
53
|
+
let currentHour;
|
|
54
|
+
if (tz) {
|
|
55
|
+
try {
|
|
56
|
+
const fmt = new Intl.DateTimeFormat("en-US", { timeZone: tz, hour: "2-digit", hour12: false });
|
|
57
|
+
currentHour = Number(fmt.format(now).replace(/\D/g, "").slice(0, 2));
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
currentHour = now.getUTCHours();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
currentHour = now.getUTCHours();
|
|
65
|
+
}
|
|
66
|
+
if (currentHour < fromHour || currentHour >= toHour)
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
function parseDays(spec) {
|
|
72
|
+
const map = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
|
|
73
|
+
// "mon-fri"
|
|
74
|
+
if (/^[a-z]{3}-[a-z]{3}$/i.test(spec)) {
|
|
75
|
+
const [from, to] = spec.toLowerCase().split("-");
|
|
76
|
+
const fi = map.indexOf(from);
|
|
77
|
+
const ti = map.indexOf(to);
|
|
78
|
+
if (fi === -1 || ti === -1)
|
|
79
|
+
return [];
|
|
80
|
+
const out = [];
|
|
81
|
+
for (let i = fi; i !== ti; i = (i + 1) % 7)
|
|
82
|
+
out.push(map[i]);
|
|
83
|
+
out.push(map[ti]);
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
// "mon,wed,fri"
|
|
87
|
+
return spec.toLowerCase().split(",").map(s => s.trim()).filter(Boolean);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Find the first matching rule for a (method, path) pair in a profile config.
|
|
91
|
+
* Returns null if no rule matches. Supports both v1 and v2 shapes.
|
|
92
|
+
*/
|
|
93
|
+
export function findMatchingRule(profileConfig, method, path) {
|
|
94
|
+
if (profileConfig.rules && profileConfig.rules.length > 0) {
|
|
95
|
+
for (const rule of profileConfig.rules) {
|
|
96
|
+
if (methodMatches(rule.match?.method, method) && pathMatches(rule.match?.path, path)) {
|
|
97
|
+
return rule;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
14
103
|
export function enforceWritePolicy(ctx, method, path) {
|
|
15
104
|
const policyPath = ctx.policyFile?.trim() || process.env.HSCLI_POLICY_FILE?.trim();
|
|
16
105
|
if (!policyPath)
|
|
17
106
|
return;
|
|
18
107
|
const config = readPolicyFile(policyPath);
|
|
19
|
-
const
|
|
108
|
+
const profileConfig = config.profiles?.[ctx.profile] ?? config.defaults ?? {};
|
|
20
109
|
const defaults = config.defaults ?? {};
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
110
|
+
// v2 style: find matching rule, apply its action
|
|
111
|
+
const matched = findMatchingRule(profileConfig, method, path) ?? findMatchingRule(defaults, method, path);
|
|
112
|
+
if (matched) {
|
|
113
|
+
// Time window check first — outside window always denies
|
|
114
|
+
if (!isWithinWindow(matched.window)) {
|
|
115
|
+
throw new CliError("POLICY_OUT_OF_WINDOW", `Policy rule '${matched.name ?? "(unnamed)"}' is outside its allowed time window (${matched.window?.days ?? "any"} ${matched.window?.hours ?? "any"} ${matched.window?.tz ?? "UTC"}).`);
|
|
116
|
+
}
|
|
117
|
+
if (matched.action === "deny") {
|
|
118
|
+
throw new CliError("POLICY_RULE_DENY", `Policy rule '${matched.name ?? "(unnamed)"}' denies ${method} ${path}.`);
|
|
119
|
+
}
|
|
120
|
+
if (matched.requireChangeTicket && !ctx.changeTicket?.trim()) {
|
|
121
|
+
throw new CliError("POLICY_CHANGE_TICKET_REQUIRED", `Policy rule '${matched.name ?? "(unnamed)"}' requires --change-ticket for ${method} ${path}.`);
|
|
122
|
+
}
|
|
123
|
+
if (matched.requireApproval) {
|
|
124
|
+
// v0.7.0: approval flow is not yet implemented. Log + deny with
|
|
125
|
+
// actionable error. Approvals land in v0.7.1 (webhook/Slack).
|
|
126
|
+
throw new CliError("POLICY_APPROVAL_REQUIRED", `Policy rule '${matched.name ?? "(unnamed)"}' requires approval (${matched.requireApproval}). Approval workflow lands in v0.7.1.`);
|
|
127
|
+
}
|
|
128
|
+
// action === "allow" (or undefined → allow by default when matched)
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
// No rule matched → use defaultAction
|
|
132
|
+
const defaultAction = profileConfig.defaultAction ?? defaults.defaultAction;
|
|
133
|
+
if (defaultAction === "deny") {
|
|
134
|
+
throw new CliError("POLICY_DEFAULT_DENY", `No policy rule matched ${method} ${path} and profile default action is 'deny'.`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// v1 legacy flat fields — still honored for backward compat
|
|
138
|
+
const profileFlat = profileConfig;
|
|
139
|
+
const allowWrite = profileFlat.allowWrite ?? defaults.allowWrite ?? true;
|
|
140
|
+
const allowDelete = profileFlat.allowDelete ?? defaults.allowDelete ?? true;
|
|
141
|
+
const requireChangeTicketLegacy = profileFlat.requireChangeTicket ?? defaults.requireChangeTicket ?? false;
|
|
24
142
|
if (!allowWrite) {
|
|
25
143
|
throw new CliError("POLICY_WRITE_BLOCKED", `Policy blocks write operations for profile '${ctx.profile}'.`);
|
|
26
144
|
}
|
|
27
145
|
if (method === "DELETE" && !allowDelete) {
|
|
28
146
|
throw new CliError("POLICY_DELETE_BLOCKED", `Policy blocks delete operations for profile '${ctx.profile}'.`);
|
|
29
147
|
}
|
|
30
|
-
if (
|
|
148
|
+
if (requireChangeTicketLegacy && !ctx.changeTicket?.trim()) {
|
|
31
149
|
throw new CliError("POLICY_CHANGE_TICKET_REQUIRED", `Profile '${ctx.profile}' requires --change-ticket for write operations.`);
|
|
32
150
|
}
|
|
33
151
|
const blockedPrefixes = config.blockedMethodPathPrefixes?.[method] ?? [];
|
package/dist/core/policy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/core/policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/core/policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 2,
|
|
3
|
+
"description": "Allow writes only during business hours (9am-5pm, Mon-Fri) in US/Eastern timezone. Outside the window, POST/PATCH/PUT/DELETE are denied. Adjust 'tz' to match your portal.",
|
|
4
|
+
"profiles": {
|
|
5
|
+
"default": {
|
|
6
|
+
"defaultAction": "allow",
|
|
7
|
+
"rules": [
|
|
8
|
+
{
|
|
9
|
+
"name": "block-writes-outside-business-hours",
|
|
10
|
+
"match": { "method": "*", "path": "**" },
|
|
11
|
+
"action": "allow",
|
|
12
|
+
"window": {
|
|
13
|
+
"tz": "US/Eastern",
|
|
14
|
+
"hours": "09-17",
|
|
15
|
+
"days": "mon-fri"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 2,
|
|
3
|
+
"description": "Every POST/PATCH/PUT/DELETE must reference a change ticket via --change-ticket <id>. Reads are always allowed.",
|
|
4
|
+
"profiles": {
|
|
5
|
+
"default": {
|
|
6
|
+
"defaultAction": "allow",
|
|
7
|
+
"rules": [
|
|
8
|
+
{
|
|
9
|
+
"name": "writes-require-change-ticket",
|
|
10
|
+
"match": { "method": "POST", "path": "**" },
|
|
11
|
+
"action": "allow",
|
|
12
|
+
"requireChangeTicket": true
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"name": "patches-require-change-ticket",
|
|
16
|
+
"match": { "method": "PATCH", "path": "**" },
|
|
17
|
+
"action": "allow",
|
|
18
|
+
"requireChangeTicket": true
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "puts-require-change-ticket",
|
|
22
|
+
"match": { "method": "PUT", "path": "**" },
|
|
23
|
+
"action": "allow",
|
|
24
|
+
"requireChangeTicket": true
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "deletes-require-change-ticket",
|
|
28
|
+
"match": { "method": "DELETE", "path": "**" },
|
|
29
|
+
"action": "allow",
|
|
30
|
+
"requireChangeTicket": true
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 2,
|
|
3
|
+
"description": "Strict compliance profile: writes only in business hours, every write requires a change ticket, all DELETEs blocked, GDPR endpoints require extra approval flow.",
|
|
4
|
+
"profiles": {
|
|
5
|
+
"default": {
|
|
6
|
+
"defaultAction": "allow",
|
|
7
|
+
"rules": [
|
|
8
|
+
{
|
|
9
|
+
"name": "gdpr-endpoints-need-approval",
|
|
10
|
+
"match": { "method": "*", "path": "**/gdpr-delete**" },
|
|
11
|
+
"action": "allow",
|
|
12
|
+
"requireApproval": "manual"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"name": "block-all-deletes",
|
|
16
|
+
"match": { "method": "DELETE", "path": "**" },
|
|
17
|
+
"action": "deny"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "writes-require-change-ticket-and-hours",
|
|
21
|
+
"match": { "method": "POST", "path": "**" },
|
|
22
|
+
"action": "allow",
|
|
23
|
+
"requireChangeTicket": true,
|
|
24
|
+
"window": { "tz": "US/Eastern", "hours": "09-17", "days": "mon-fri" }
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "patches-require-change-ticket-and-hours",
|
|
28
|
+
"match": { "method": "PATCH", "path": "**" },
|
|
29
|
+
"action": "allow",
|
|
30
|
+
"requireChangeTicket": true,
|
|
31
|
+
"window": { "tz": "US/Eastern", "hours": "09-17", "days": "mon-fri" }
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 2,
|
|
3
|
+
"description": "Allow POST/PATCH/PUT but block all DELETE operations. Good for environments where accidental deletion is expensive and archiving is preferred.",
|
|
4
|
+
"profiles": {
|
|
5
|
+
"default": {
|
|
6
|
+
"defaultAction": "allow",
|
|
7
|
+
"rules": [
|
|
8
|
+
{
|
|
9
|
+
"name": "block-all-deletes",
|
|
10
|
+
"match": { "method": "DELETE", "path": "**" },
|
|
11
|
+
"action": "deny"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"allowDelete": false
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 2,
|
|
3
|
+
"description": "Block all writes on the 'default' profile. For ops/support engineers exploring a portal without risking accidental mutation.",
|
|
4
|
+
"profiles": {
|
|
5
|
+
"default": {
|
|
6
|
+
"defaultAction": "deny",
|
|
7
|
+
"rules": [
|
|
8
|
+
{
|
|
9
|
+
"name": "allow-all-reads",
|
|
10
|
+
"match": { "method": "GET", "path": "**" },
|
|
11
|
+
"action": "allow"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"allowWrite": false
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revfleet/hscli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Headless HubSpot CLI + MCP server. 100% public API coverage (1180 endpoints, 55+ command domains) — full portal, no UI dependency. Enterprise safety rails, self-hosted.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
},
|
|
57
57
|
"files": [
|
|
58
58
|
"dist",
|
|
59
|
+
"docs/policy-templates",
|
|
59
60
|
"README.md",
|
|
60
61
|
"LICENSE",
|
|
61
62
|
"SECURITY.md",
|