speclock 3.0.0 → 3.5.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/README.md CHANGED
@@ -61,6 +61,10 @@ No other tool does this. Not Claude's native memory. Not Mem0. Not CLAUDE.md fil
61
61
  | **Hard enforcement (block violations)** | No | No | No | **Yes — hard mode blocks above threshold** |
62
62
  | **API Key Auth + RBAC** | No | No | No | **Yes** |
63
63
  | **Encrypted Storage (AES-256)** | No | No | No | **Yes** |
64
+ | **Policy-as-Code DSL** | No | No | No | **Yes — declarative YAML rules** |
65
+ | **OAuth/OIDC SSO** | No | No | No | **Yes — Okta, Azure AD, Auth0** |
66
+ | **Admin Dashboard** | No | No | No | **Yes — real-time web UI** |
67
+ | **Telemetry & Analytics** | No | No | No | **Yes — opt-in usage insights** |
64
68
  | Multi-agent timeline | No | No | No | **Yes** |
65
69
  | Cross-platform | Claude only | MCP only | Tool-specific | **Universal (MCP + npm)** |
66
70
 
@@ -195,10 +199,10 @@ Result: NO CONFLICT (confidence: 7%)
195
199
  | Mode | Platforms | How It Works |
196
200
  |------|-----------|--------------|
197
201
  | **MCP Remote** | Lovable, bolt.diy, Base44 | Connect via URL — no install needed |
198
- | **MCP Local** | Claude Code, Cursor, Windsurf, Cline | `npx speclock serve` — 28 tools via MCP |
202
+ | **MCP Local** | Claude Code, Cursor, Windsurf, Cline | `npx speclock serve` — 31 tools via MCP |
199
203
  | **npm File-Based** | Bolt.new, Aider, Rocket.new | `npx speclock setup` — AI reads SPECLOCK.md + uses CLI |
200
204
 
201
- ## 28 MCP Tools
205
+ ## 31 MCP Tools
202
206
 
203
207
  ### Memory Management
204
208
  | Tool | Purpose |
@@ -260,6 +264,13 @@ Result: NO CONFLICT (confidence: 7%)
260
264
  | `speclock_semantic_audit` | Semantic pre-commit: analyze code changes vs locks |
261
265
  | `speclock_override_history` | View lock override history for audit review |
262
266
 
267
+ ### Enterprise Platform (v3.5)
268
+ | Tool | Purpose |
269
+ |------|---------|
270
+ | `speclock_policy_evaluate` | Evaluate policy-as-code rules against proposed actions |
271
+ | `speclock_policy_manage` | CRUD for policy rules — list, add, remove, init, export |
272
+ | `speclock_telemetry` | View opt-in telemetry summary and usage analytics |
273
+
263
274
  ## Auto-Guard: Locks That Actually Work
264
275
 
265
276
  When you add a lock, SpecLock **automatically finds and guards related files**:
@@ -334,6 +345,16 @@ speclock override <lockId> <reason> # Override a lock with justification
334
345
  speclock overrides [--lock <id>] # Show override history
335
346
  speclock audit-semantic # Semantic pre-commit audit
336
347
 
348
+ # Enterprise Platform (v3.5)
349
+ speclock policy list # List policy rules
350
+ speclock policy init # Initialize policy-as-code
351
+ speclock policy add <name> --files <pattern> --actions <types> --enforce <level>
352
+ speclock policy evaluate --files <f> --type <t> # Evaluate against rules
353
+ speclock policy export # Export policy as portable YAML
354
+ speclock telemetry status # View telemetry summary
355
+ speclock sso status # Show SSO configuration
356
+ speclock sso configure # Configure OAuth/OIDC SSO
357
+
337
358
  # Other
338
359
  speclock status # Show brain summary
339
360
  speclock serve [--project <path>] # Start MCP server
@@ -419,7 +440,58 @@ SHA-256 hashed keys stored server-side. HTTP transport uses `Authorization: Bear
419
440
  Transparent encrypt-on-write / decrypt-on-read for `brain.json` and `events.log`. Encryption key is derived via PBKDF2 from the `SPECLOCK_ENCRYPTION_KEY` environment variable. Authenticated encryption (GCM) ensures both confidentiality and integrity. **HIPAA 2026 compliant.**
420
441
 
421
442
  ### Test Coverage
422
- **300 tests passing** (up from 186 in v2.5). Full coverage for authentication, authorization, encryption, semantic detection, and audit chain integrity.
443
+ **330+ tests passing** across 6 test suites. Full coverage for authentication, authorization, encryption, semantic detection, audit chain integrity, policy-as-code, telemetry, and SSO.
444
+
445
+ ## Enterprise Platform (v3.5)
446
+
447
+ ### Policy-as-Code DSL
448
+ Declarative YAML-based policy rules for enterprise constraint enforcement:
449
+
450
+ ```yaml
451
+ # .speclock/policy.yml
452
+ rules:
453
+ - name: "HIPAA PHI Protection"
454
+ match:
455
+ files: ["**/patient/**", "**/medical/**"]
456
+ actions: [delete, modify, export]
457
+ enforce: block
458
+ severity: critical
459
+ notify: ["security@company.com", "slack:#compliance"]
460
+ ```
461
+
462
+ - **File pattern matching**: Glob patterns (`**/patient/**`, `src/api/*.js`)
463
+ - **Action-type filtering**: Block specific operations (delete, modify, create, export)
464
+ - **Enforcement levels**: `block` (hard stop), `warn` (advisory), `log` (record only)
465
+ - **Severity levels**: critical, high, medium, low
466
+ - **Notification hooks**: Email, Slack, webhook channels
467
+ - **Import/export**: Share policies between organizations
468
+
469
+ ### OAuth/OIDC SSO
470
+ Enterprise single sign-on with corporate identity providers:
471
+
472
+ - **Providers**: Okta, Azure AD, Auth0, any OIDC-compliant IdP
473
+ - **PKCE flow**: Authorization Code with Proof Key (S256)
474
+ - **Role mapping**: Map OIDC groups/roles to SpecLock roles (viewer/developer/architect/admin)
475
+ - **Session management**: 8-hour TTL, token refresh, session listing/revocation
476
+ - **MCP June 2025 spec**: OAuth compliance
477
+
478
+ ### Admin Dashboard
479
+ Real-time web UI served from the HTTP server:
480
+
481
+ - **Access**: `http://localhost:PORT/dashboard`
482
+ - **Views**: Lock overview, violation timeline, session history, health score
483
+ - **Metrics**: Enforcement mode, auth status, encryption status, audit chain integrity
484
+ - **Zero dependencies**: Vanilla HTML/JS — no framework overhead
485
+ - **Auto-refresh**: Updates every 30 seconds
486
+
487
+ ### Telemetry & Analytics
488
+ Opt-in usage insights for product improvement:
489
+
490
+ - **Disabled by default** — enable with `SPECLOCK_TELEMETRY=true`
491
+ - **Tracks**: Tool usage counts, conflict detection rates, response times, feature adoption
492
+ - **Never tracks**: Lock content, project names, any PII
493
+ - **Local storage**: `.speclock/telemetry.json` with optional remote flush
494
+ - **30-day rolling window**: Daily stats with trend analysis
423
495
 
424
496
  ---
425
497
 
@@ -431,7 +503,7 @@ Transparent encrypt-on-write / decrypt-on-read for `brain.json` and `events.log`
431
503
  └──────────────┬──────────────────┬────────────────────┘
432
504
  │ │
433
505
  MCP Protocol File-Based (npm)
434
- (28 tool calls) (reads SPECLOCK.md +
506
+ (31 tool calls) (reads SPECLOCK.md +
435
507
  .speclock/context/latest.md,
436
508
  runs CLI commands)
437
509
  │ │
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "speclock",
3
- "version": "3.0.0",
4
- "description": "AI constraint engine with API key auth, RBAC, AES-256-GCM encryption, hard enforcement, semantic pre-commit, HMAC audit chain, SOC 2/HIPAA compliance. 100% detection, 0% false positives. 28 MCP tools + CLI. Enterprise-ready.",
3
+ "version": "3.5.0",
4
+ "description": "AI constraint engine with Policy-as-Code DSL, OAuth/OIDC SSO, admin dashboard, telemetry, API key auth, RBAC, AES-256-GCM encryption, hard enforcement, semantic pre-commit, HMAC audit chain, SOC 2/HIPAA compliance. 100% detection, 0% false positives. 31 MCP tools + CLI. Enterprise platform.",
5
5
  "type": "module",
6
6
  "main": "src/mcp/server.js",
7
7
  "bin": {
@@ -41,7 +41,13 @@
41
41
  "aes-256",
42
42
  "api-key",
43
43
  "authentication",
44
- "rbac"
44
+ "rbac",
45
+ "policy-as-code",
46
+ "sso",
47
+ "oauth",
48
+ "oidc",
49
+ "dashboard",
50
+ "telemetry"
45
51
  ],
46
52
  "author": "Sandeep Roy (https://github.com/sgroy10)",
47
53
  "license": "MIT",
@@ -64,6 +70,7 @@
64
70
  "files": [
65
71
  "bin/",
66
72
  "src/",
73
+ "src/dashboard/",
67
74
  "README.md",
68
75
  "SPECLOCK-INSTRUCTIONS.md",
69
76
  "LICENSE"
package/src/cli/index.js CHANGED
@@ -43,6 +43,24 @@ import {
43
43
  listApiKeys,
44
44
  } from "../core/auth.js";
45
45
  import { isEncryptionEnabled } from "../core/crypto.js";
46
+ import {
47
+ initPolicy,
48
+ addPolicyRule,
49
+ removePolicyRule,
50
+ listPolicyRules,
51
+ evaluatePolicy,
52
+ exportPolicy,
53
+ importPolicy,
54
+ } from "../core/policy.js";
55
+ import {
56
+ isTelemetryEnabled,
57
+ getTelemetrySummary,
58
+ } from "../core/telemetry.js";
59
+ import {
60
+ isSSOEnabled,
61
+ getSSOConfig,
62
+ saveSSOConfig,
63
+ } from "../core/sso.js";
46
64
 
47
65
  // --- Argument parsing ---
48
66
 
@@ -98,7 +116,7 @@ function refreshContext(root) {
98
116
 
99
117
  function printHelp() {
100
118
  console.log(`
101
- SpecLock v3.0.0 — AI Constraint Engine (Auth + RBAC + Encryption + Hard Enforcement)
119
+ SpecLock v3.5.0 — AI Constraint Engine (Policy-as-Code + SSO + Dashboard + Telemetry + Auth + RBAC + Encryption)
102
120
  Developed by Sandeep Roy (github.com/sgroy10)
103
121
 
104
122
  Usage: speclock <command> [options]
@@ -146,6 +164,17 @@ Options:
146
164
 
147
165
  Templates: nextjs, react, express, supabase, stripe, security-hardened
148
166
 
167
+ Policy-as-Code (v3.5):
168
+ policy list List all policy rules
169
+ policy init Initialize policy-as-code
170
+ policy add --name <name> Add a policy rule (--files, --enforce, --severity)
171
+ policy remove <ruleId> Remove a policy rule
172
+ policy evaluate <action> Evaluate action against policy rules
173
+ policy export Export policy as YAML
174
+ telemetry [status] Show telemetry status and analytics
175
+ sso status Show SSO configuration
176
+ sso configure --issuer <url> Configure SSO (--client-id, --client-secret)
177
+
149
178
  Security (v3.0):
150
179
  auth status Show auth status and active keys
151
180
  auth create-key --role <role> Create API key (viewer/developer/architect/admin)
@@ -210,6 +239,10 @@ function showStatus(root) {
210
239
  console.log(`Recent changes: ${brain.state.recentChanges.length}`);
211
240
  console.log(`Auth: ${isAuthEnabled(root) ? "enabled" : "disabled"}`);
212
241
  console.log(`Encryption: ${isEncryptionEnabled() ? "enabled (AES-256-GCM)" : "disabled"}`);
242
+ const policyRules = listPolicyRules(root);
243
+ console.log(`Policy rules: ${policyRules.active}/${policyRules.total}`);
244
+ console.log(`Telemetry: ${isTelemetryEnabled() ? "enabled" : "disabled"}`);
245
+ console.log(`SSO: ${isSSOEnabled(root) ? "configured" : "not configured"}`);
213
246
  console.log("");
214
247
  }
215
248
 
@@ -902,6 +935,146 @@ Tip: When starting a new chat, tell the AI:
902
935
  process.exit(1);
903
936
  }
904
937
 
938
+ // --- POLICY (v3.5) ---
939
+ if (cmd === "policy") {
940
+ const sub = args[0];
941
+ if (!sub || sub === "list") {
942
+ const result = listPolicyRules(root);
943
+ console.log(`\nPolicy Rules (${result.active}/${result.total} active):`);
944
+ console.log("=".repeat(50));
945
+ if (result.rules.length === 0) {
946
+ console.log(" No rules. Run 'speclock policy init' to create a policy.");
947
+ } else {
948
+ for (const r of result.rules) {
949
+ const status = r.active !== false ? "active" : "inactive";
950
+ console.log(` ${r.id} — ${r.name} [${r.enforce}/${r.severity}] (${status})`);
951
+ console.log(` Files: ${(r.match?.files || []).join(", ")}`);
952
+ console.log(` Actions: ${(r.match?.actions || []).join(", ")}`);
953
+ console.log("");
954
+ }
955
+ }
956
+ return;
957
+ }
958
+ if (sub === "init") {
959
+ const result = initPolicy(root);
960
+ if (!result.success) { console.error(result.error); process.exit(1); }
961
+ console.log("Policy-as-code initialized. Edit .speclock/policy.yml to add rules.");
962
+ return;
963
+ }
964
+ if (sub === "add") {
965
+ const flags = parseFlags(args.slice(1));
966
+ const name = flags.name || flags._.join(" ");
967
+ if (!name) { console.error("Usage: speclock policy add --name <name> --files '**/*.js' --enforce block"); process.exit(1); }
968
+ const rule = {
969
+ name,
970
+ description: flags.description || "",
971
+ match: {
972
+ files: flags.files ? flags.files.split(",").map(s => s.trim()) : ["**/*"],
973
+ actions: flags.actions ? flags.actions.split(",").map(s => s.trim()) : ["modify", "delete"],
974
+ },
975
+ enforce: flags.enforce || "warn",
976
+ severity: flags.severity || "medium",
977
+ notify: flags.notify ? flags.notify.split(",").map(s => s.trim()) : [],
978
+ };
979
+ const result = addPolicyRule(root, rule);
980
+ if (!result.success) { console.error(result.error); process.exit(1); }
981
+ console.log(`Policy rule added: "${result.rule.name}" (${result.ruleId}) [${result.rule.enforce}]`);
982
+ return;
983
+ }
984
+ if (sub === "remove") {
985
+ const ruleId = args[1];
986
+ if (!ruleId) { console.error("Usage: speclock policy remove <ruleId>"); process.exit(1); }
987
+ const result = removePolicyRule(root, ruleId);
988
+ if (!result.success) { console.error(result.error); process.exit(1); }
989
+ console.log(`Policy rule removed: "${result.removed.name}"`);
990
+ return;
991
+ }
992
+ if (sub === "evaluate") {
993
+ const text = args.slice(1).join(" ");
994
+ if (!text) { console.error("Usage: speclock policy evaluate 'what you plan to do'"); process.exit(1); }
995
+ const result = evaluatePolicy(root, { description: text, text, type: "modify" });
996
+ if (result.passed) {
997
+ console.log(`Policy check passed. ${result.rulesChecked} rules evaluated.`);
998
+ } else {
999
+ console.log(`\nPolicy Violations (${result.violations.length}):`);
1000
+ for (const v of result.violations) {
1001
+ console.log(` [${v.severity.toUpperCase()}] ${v.ruleName} (${v.enforce})`);
1002
+ if (v.matchedFiles.length) console.log(` Files: ${v.matchedFiles.join(", ")}`);
1003
+ }
1004
+ if (result.blocked) process.exit(1);
1005
+ }
1006
+ return;
1007
+ }
1008
+ if (sub === "export") {
1009
+ const result = exportPolicy(root);
1010
+ if (!result.success) { console.error(result.error); process.exit(1); }
1011
+ console.log(result.yaml);
1012
+ return;
1013
+ }
1014
+ console.error("Usage: speclock policy <list|init|add|remove|evaluate|export>");
1015
+ process.exit(1);
1016
+ }
1017
+
1018
+ // --- TELEMETRY (v3.5) ---
1019
+ if (cmd === "telemetry") {
1020
+ const sub = args[0];
1021
+ if (sub === "status" || !sub) {
1022
+ const enabled = isTelemetryEnabled();
1023
+ console.log(`\nTelemetry: ${enabled ? "ENABLED" : "DISABLED"}`);
1024
+ if (!enabled) {
1025
+ console.log("Set SPECLOCK_TELEMETRY=true to enable anonymous usage analytics.");
1026
+ return;
1027
+ }
1028
+ const summary = getTelemetrySummary(root);
1029
+ console.log(`Total calls: ${summary.totalCalls}`);
1030
+ console.log(`Avg response: ${summary.avgResponseMs}ms`);
1031
+ console.log(`Sessions: ${summary.sessions.total}`);
1032
+ console.log(`Conflicts: ${summary.conflicts.total} (blocked: ${summary.conflicts.blocked})`);
1033
+ if (summary.topTools.length > 0) {
1034
+ console.log(`\nTop tools:`);
1035
+ for (const t of summary.topTools.slice(0, 5)) {
1036
+ console.log(` ${t.name}: ${t.count} calls`);
1037
+ }
1038
+ }
1039
+ return;
1040
+ }
1041
+ console.error("Usage: speclock telemetry [status]");
1042
+ process.exit(1);
1043
+ }
1044
+
1045
+ // --- SSO (v3.5) ---
1046
+ if (cmd === "sso") {
1047
+ const sub = args[0];
1048
+ if (sub === "status" || !sub) {
1049
+ const enabled = isSSOEnabled(root);
1050
+ const config = getSSOConfig(root);
1051
+ console.log(`\nSSO: ${enabled ? "CONFIGURED" : "NOT CONFIGURED"}`);
1052
+ if (enabled) {
1053
+ console.log(`Issuer: ${config.issuer}`);
1054
+ console.log(`Client ID: ${config.clientId}`);
1055
+ console.log(`Redirect: ${config.redirectUri}`);
1056
+ console.log(`Default role: ${config.defaultRole}`);
1057
+ } else {
1058
+ console.log("Set SPECLOCK_SSO_ISSUER and SPECLOCK_SSO_CLIENT_ID to enable SSO.");
1059
+ }
1060
+ return;
1061
+ }
1062
+ if (sub === "configure") {
1063
+ const flags = parseFlags(args.slice(1));
1064
+ const config = getSSOConfig(root);
1065
+ if (flags.issuer) config.issuer = flags.issuer;
1066
+ if (flags["client-id"]) config.clientId = flags["client-id"];
1067
+ if (flags["client-secret"]) config.clientSecret = flags["client-secret"];
1068
+ if (flags["redirect-uri"]) config.redirectUri = flags["redirect-uri"];
1069
+ if (flags["default-role"]) config.defaultRole = flags["default-role"];
1070
+ saveSSOConfig(root, config);
1071
+ console.log("SSO configuration saved.");
1072
+ return;
1073
+ }
1074
+ console.error("Usage: speclock sso <status|configure> [--issuer URL --client-id ID]");
1075
+ process.exit(1);
1076
+ }
1077
+
905
1078
  // --- ENCRYPT STATUS (v3.0) ---
906
1079
  if (cmd === "encrypt") {
907
1080
  const sub = args[0];
@@ -9,7 +9,7 @@
9
9
  import { readBrain, readEvents } from "./storage.js";
10
10
  import { verifyAuditChain } from "./audit.js";
11
11
 
12
- const VERSION = "3.0.0";
12
+ const VERSION = "3.5.0";
13
13
 
14
14
  // PHI-related keywords for HIPAA filtering
15
15
  const PHI_KEYWORDS = [
@@ -556,3 +556,41 @@ export {
556
556
  decrypt,
557
557
  clearKeyCache,
558
558
  } from "./crypto.js";
559
+
560
+ // --- Policy-as-Code (v3.5) ---
561
+ export {
562
+ loadPolicy,
563
+ savePolicy,
564
+ initPolicy,
565
+ addPolicyRule,
566
+ removePolicyRule,
567
+ listPolicyRules,
568
+ evaluatePolicy,
569
+ exportPolicy,
570
+ importPolicy,
571
+ generateNotifications,
572
+ } from "./policy.js";
573
+
574
+ // --- Telemetry & Analytics (v3.5) ---
575
+ export {
576
+ isTelemetryEnabled,
577
+ trackToolUsage,
578
+ trackConflict,
579
+ trackFeature,
580
+ trackSession,
581
+ getTelemetrySummary,
582
+ flushToRemote,
583
+ resetTelemetry,
584
+ } from "./telemetry.js";
585
+
586
+ // --- OAuth/OIDC SSO (v3.5) ---
587
+ export {
588
+ isSSOEnabled,
589
+ getSSOConfig,
590
+ saveSSOConfig,
591
+ getAuthorizationUrl,
592
+ handleCallback,
593
+ validateSession,
594
+ revokeSession,
595
+ listSessions,
596
+ } from "./sso.js";