@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 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,3 @@
1
+ import { Command } from "commander";
2
+ import type { CliContext } from "../../core/output.js";
3
+ export declare function registerAudit(program: Command, getCtx: () => CliContext): void;
@@ -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,3 @@
1
+ import { Command } from "commander";
2
+ import type { CliContext } from "../../core/output.js";
3
+ export declare function registerPolicy(program: Command, getCtx: () => CliContext): void;
@@ -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":"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"}
@@ -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;
@@ -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 profileRule = config.profiles?.[ctx.profile] ?? {};
108
+ const profileConfig = config.profiles?.[ctx.profile] ?? config.defaults ?? {};
20
109
  const defaults = config.defaults ?? {};
21
- const allowWrite = profileRule.allowWrite ?? defaults.allowWrite ?? true;
22
- const allowDelete = profileRule.allowDelete ?? defaults.allowDelete ?? false;
23
- const requireChangeTicket = profileRule.requireChangeTicket ?? defaults.requireChangeTicket ?? false;
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 (requireChangeTicket && !ctx.changeTicket?.trim()) {
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] ?? [];
@@ -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;AAcvC,SAAS,cAAc,CAAC,IAAY;IAClC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,QAAQ,CAAC,uBAAuB,EAAE,0BAA0B,IAAI,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAiB,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,QAAQ,CAAC,qBAAqB,EAAE,wBAAwB,IAAI,EAAE,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAe,EAAE,MAA2C,EAAE,IAAY;IAC3G,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC;IACnF,IAAI,CAAC,UAAU;QAAE,OAAO;IAExB,MAAM,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAe,MAAM,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IACrE,MAAM,QAAQ,GAAe,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;IACnD,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,IAAI,QAAQ,CAAC,UAAU,IAAI,IAAI,CAAC;IACzE,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,IAAI,QAAQ,CAAC,WAAW,IAAI,KAAK,CAAC;IAC7E,MAAM,mBAAmB,GAAG,WAAW,CAAC,mBAAmB,IAAI,QAAQ,CAAC,mBAAmB,IAAI,KAAK,CAAC;IAErG,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,QAAQ,CAAC,sBAAsB,EAAE,+CAA+C,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;IAC7G,CAAC;IACD,IAAI,MAAM,KAAK,QAAQ,IAAI,CAAC,WAAW,EAAE,CAAC;QACxC,MAAM,IAAI,QAAQ,CAAC,uBAAuB,EAAE,gDAAgD,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;IAC/G,CAAC;IACD,IAAI,mBAAmB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,EAAE,EAAE,CAAC;QACrD,MAAM,IAAI,QAAQ,CAAC,+BAA+B,EAAE,YAAY,GAAG,CAAC,OAAO,kDAAkD,CAAC,CAAC;IACjI,CAAC;IAED,MAAM,eAAe,GAAG,MAAM,CAAC,yBAAyB,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACzE,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,QAAQ,CAAC,qBAAqB,EAAE,iBAAiB,MAAM,aAAa,IAAI,IAAI,CAAC,CAAC;IAC1F,CAAC;AACH,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.6.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",