@compr/opscontext-mcp 2.0.0 → 2.0.2
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 +30 -0
- package/dist/activation.js +6 -2
- package/dist/agents.js +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.js +2 -2
- package/dist/license-sig.js +14 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to OpsContext for AI Agents (previously ContextEngine — MCP server + CLI) are documented here.
|
|
4
4
|
|
|
5
|
+
## [2.0.2] — 2026-06-11 — HTML score report browser tab title → OpsContext
|
|
6
|
+
|
|
7
|
+
Tiny patch release. One change:
|
|
8
|
+
- `src/agents.ts` `generateScoreHTML()` — `<title>` tag changed from `ContextEngine Score Report` to `OpsContext Score Report`. Visible in the browser tab when a paying user (or the `score --html` CLI flag) generates the report. No functional change.
|
|
9
|
+
|
|
10
|
+
Why patch: cosmetic-only rename of a user-visible string. No new APIs, no contract changes, no behavior change for any caller.
|
|
11
|
+
|
|
12
|
+
Paired with the VS Code extension `0.8.1` release that adds the `OpsContext: Generate HTML Score Report (PRO)` command — together they close the visible-paid-feature gap from the 2.0.0 rebrand (advertised "HTML score reports — ✓" but no clickable path).
|
|
13
|
+
|
|
14
|
+
## [2.0.1] — 2026-06-11 — Flag day reached early + pricing href fix
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- **Legacy SHA-256 license signatures are now REJECTED** (the "flag day" originally scheduled for 2026-08-15). Brought forward to today because the production licence DB analysis showed the customer base is effectively empty — the only real active license belongs to the maintainer, who has already re-activated to Ed25519. Three other "active" rows in the DB are licenses that expired 2026-04-27 and are already failing the expiry check on every load. Bringing the flag day forward by ~10 weeks costs nothing real and removes the half-open security loophole sooner.
|
|
18
|
+
- `src/license-sig.ts` `verifyLicenseSignature()` — the 64-char hex branch now returns `{ ok: false, reason: "Legacy SHA-256 ... reactivate at ..." }` instead of `{ ok: true, mode: "legacy-grandfathered" }`.
|
|
19
|
+
- LOCK comment on the file updated: the flag-day-reached marker replaces the warning-about-grandfathering text.
|
|
20
|
+
- `src/activation.ts` `loadLicense()` — the `if (verify.mode === "legacy-grandfathered")` branch is now defensive dead code (kept since the union type still carries the variant for backward compat with audit-log records).
|
|
21
|
+
- `tests/license-sig.test.ts` — the test that previously asserted `mode: "legacy-grandfathered"` now asserts `ok: false` with a reactivation pointer in the reason. Test renamed `REJECTS legacy SHA-256 hex signature (flag day reached 2026-06-11)`.
|
|
22
|
+
- **Pricing URL href fix** in 5 source files. The user-facing strings referenced `https://compr.ch/contextengine/pricing` which returns 404; only `https://api.compr.ch/contextengine/pricing` resolves. Files: `src/activation.ts:145, 450`, `src/cli.ts:1882`, `src/index.ts:1132, 1170`.
|
|
23
|
+
- **`docs/deploy/ED25519_FLAG_DAY.md`** can now be archived — the action it scheduled was completed today. Leaving the file in place as a historical record.
|
|
24
|
+
- **`server/deploy.sh` hardened** (this was committed earlier as `bbeffe8`, but tying it to the release for context): pre-flight builds locally, smoke-tests `/health` after deploy and dies on broken state, uses the full PM2 path that actually works in non-interactive ssh shells. Supports `--dry-run`.
|
|
25
|
+
|
|
26
|
+
### Why this is patch-level, not minor
|
|
27
|
+
The behaviour change is a tightening of a check that was documented as temporary from day one. The semver contract said legacy signatures would be rejected after the flag day; the date moved up because the situation allowed it. No new features. No removed APIs.
|
|
28
|
+
|
|
29
|
+
### Notes
|
|
30
|
+
- 4 paying-customer rows in the activation DB; 1 is real and active (maintainer's enterprise license, already re-activated). The other 3 already expired April 27 and are non-active per the client's expiry check.
|
|
31
|
+
- Customer notification email (originally scheduled for 2026-08-08) skipped — would have been a no-op or a re-engagement note to the two `gmail.com` addresses whose licenses expired. Yannick can send re-engagement separately if he wants.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
5
35
|
## [2.0.0] — 2026-06-10 — Strategic pivot + Claude Code native integration (A+B+C)
|
|
6
36
|
|
|
7
37
|
### Added (Claude Code integration — A + B + C from the rebrand backlog)
|
package/dist/activation.js
CHANGED
|
@@ -98,7 +98,7 @@ export function loadLicense() {
|
|
|
98
98
|
const verify = verifyLicenseSignature(data);
|
|
99
99
|
if (!verify.ok) {
|
|
100
100
|
console.error(`[ContextEngine] ⛔ License signature rejected — ${verify.reason}. Premium features disabled. ` +
|
|
101
|
-
`Reactivate at https://compr.ch/contextengine/pricing if this surprises you.`);
|
|
101
|
+
`Reactivate at https://api.compr.ch/contextengine/pricing if this surprises you.`);
|
|
102
102
|
safeAppend("activation.signature_reject", {
|
|
103
103
|
plan: data.plan,
|
|
104
104
|
machine_id: data.machineId,
|
|
@@ -106,6 +106,10 @@ export function loadLicense() {
|
|
|
106
106
|
});
|
|
107
107
|
return null;
|
|
108
108
|
}
|
|
109
|
+
// The legacy-grandfathered branch is no longer reachable since the
|
|
110
|
+
// 2026-06-11 flag day — legacy SHA-256 signatures now return ok:false
|
|
111
|
+
// and are rejected above. Branch kept defensively in case the type
|
|
112
|
+
// union ever changes (zero cost; dead in 2.0.1+).
|
|
109
113
|
if (verify.mode === "legacy-grandfathered") {
|
|
110
114
|
console.error(`[ContextEngine] ⚠ ${verify.warning}`);
|
|
111
115
|
safeAppend("activation.legacy_signature", {
|
|
@@ -350,7 +354,7 @@ export function gateCheck(toolName) {
|
|
|
350
354
|
if (!license) {
|
|
351
355
|
return `🔒 "${toolName}" requires a ContextEngine Pro license.\n\n` +
|
|
352
356
|
`Activate with: npx contextengine activate <license-key> <email>\n` +
|
|
353
|
-
`Get a license: https://compr.ch/contextengine/pricing\n\n` +
|
|
357
|
+
`Get a license: https://api.compr.ch/contextengine/pricing\n\n` +
|
|
354
358
|
`Free tools available: search_context, list_sources, read_source, reindex, ` +
|
|
355
359
|
`save_session, load_session, list_sessions, end_session, save_learning, ` +
|
|
356
360
|
`list_learnings, import_learnings`;
|
package/dist/agents.js
CHANGED
|
@@ -1546,7 +1546,7 @@ export function generateScoreHTML(scores) {
|
|
|
1546
1546
|
<head>
|
|
1547
1547
|
<meta charset="UTF-8">
|
|
1548
1548
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1549
|
-
<title>
|
|
1549
|
+
<title>OpsContext Score Report</title>
|
|
1550
1550
|
<style>
|
|
1551
1551
|
:root {
|
|
1552
1552
|
--bg: #0f172a; --surface: #1e293b; --border: #334155;
|
package/dist/cli.js
CHANGED
|
@@ -1782,7 +1782,7 @@ else if (command === "activate") {
|
|
|
1782
1782
|
const email = process.argv[4];
|
|
1783
1783
|
if (!key || !email) {
|
|
1784
1784
|
console.error("Usage: contextengine activate <license-key> <email>");
|
|
1785
|
-
console.error("Get a license: https://compr.ch/contextengine/pricing");
|
|
1785
|
+
console.error("Get a license: https://api.compr.ch/contextengine/pricing");
|
|
1786
1786
|
process.exit(1);
|
|
1787
1787
|
}
|
|
1788
1788
|
activate(key, email).then((result) => {
|
package/dist/index.js
CHANGED
|
@@ -887,7 +887,7 @@ server.tool("import_learnings", "Bulk-import learnings from a Markdown or JSON f
|
|
|
887
887
|
// ---------------------------------------------------------------------------
|
|
888
888
|
// Tool: activate (License Activation)
|
|
889
889
|
// ---------------------------------------------------------------------------
|
|
890
|
-
server.tool("activate", "Activate a ContextEngine Pro license to unlock premium tools (score_project, run_audit, check_ports, list_projects, HTML reports). Get a license at https://compr.ch/contextengine/pricing", {
|
|
890
|
+
server.tool("activate", "Activate a ContextEngine Pro license to unlock premium tools (score_project, run_audit, check_ports, list_projects, HTML reports). Get a license at https://api.compr.ch/contextengine/pricing", {
|
|
891
891
|
license_key: z.string().describe("Your ContextEngine license key"),
|
|
892
892
|
email: z.string().describe("Email associated with the license"),
|
|
893
893
|
}, async ({ license_key, email }) => {
|
|
@@ -918,7 +918,7 @@ server.tool("activation_status", "Check current ContextEngine license status, pl
|
|
|
918
918
|
lines.push(`### 🔒 Premium Tools (requires activation)`);
|
|
919
919
|
lines.push(`- score_project, run_audit, check_ports, list_projects`);
|
|
920
920
|
lines.push(``);
|
|
921
|
-
lines.push(`Get a license: https://compr.ch/contextengine/pricing`);
|
|
921
|
+
lines.push(`Get a license: https://api.compr.ch/contextengine/pricing`);
|
|
922
922
|
lines.push(`Activate: \`npx contextengine activate <key> <email>\``);
|
|
923
923
|
}
|
|
924
924
|
return respond("activation_status", lines.join("\n"));
|
package/dist/license-sig.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// 🔒 LOCKED [LICENSE-SIG] — 2026-06-10
|
|
1
|
+
// 🔒 LOCKED [LICENSE-SIG] — 2026-06-10 (flag day reached 2026-06-11)
|
|
2
2
|
// ⛔ NEVER change canonicalPayload()'s key order or field set without
|
|
3
3
|
// bumping a new "sig_v":2 marker AND keeping v1 verification working
|
|
4
4
|
// forever. The byte output of this function is what the Ed25519
|
|
@@ -8,10 +8,11 @@
|
|
|
8
8
|
// that pins the client to the production activation server.
|
|
9
9
|
// Self-hosters override via CE_LICENSE_PUBLIC_KEY env var, which
|
|
10
10
|
// is the documented escape hatch.
|
|
11
|
-
// ⛔
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
11
|
+
// ⛔ Legacy SHA-256 signatures are NOW REJECTED (flag day reached
|
|
12
|
+
// 2026-06-11 — earlier than the originally scheduled 2026-08-15
|
|
13
|
+
// because the customer base is effectively empty and no one would
|
|
14
|
+
// be impacted). The 64-char hex shape returns ok:false with a
|
|
15
|
+
// reactivation pointer.
|
|
15
16
|
// WHY: Audit identified that loadLicense() did NOT verify the
|
|
16
17
|
// signature field — anyone could write ~/.contextengine/license.json
|
|
17
18
|
// with plan:"enterprise" and unlock all PRO tools. Security bug +
|
|
@@ -74,11 +75,16 @@ export function verifyLicenseSignature(license, publicKeyPem = process.env.CE_LI
|
|
|
74
75
|
}
|
|
75
76
|
// Legacy detection: pre-Ed25519 signatures were SHA-256 hex (64 chars).
|
|
76
77
|
// Real Ed25519 signatures are 64 raw bytes → 88-char base64.
|
|
78
|
+
// Flag day reached 2026-06-11: legacy signatures are now REJECTED.
|
|
79
|
+
// The mode "legacy-grandfathered" + the activation.legacy_signature
|
|
80
|
+
// audit event are kept in the type union for backward compatibility
|
|
81
|
+
// with existing audit log records but are no longer emitted.
|
|
77
82
|
if (/^[a-f0-9]{64}$/.test(license.signature)) {
|
|
78
83
|
return {
|
|
79
|
-
ok:
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
ok: false,
|
|
85
|
+
reason: "Legacy SHA-256 license signature is no longer accepted (flag day 2026-06-11). " +
|
|
86
|
+
"Run `npx @compr/opscontext-mcp activate <key> <email>` to refresh to an Ed25519-signed license, " +
|
|
87
|
+
"or see https://api.compr.ch/contextengine/pricing if you need a key.",
|
|
82
88
|
};
|
|
83
89
|
}
|
|
84
90
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@compr/opscontext-mcp",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "OpsContext for AI Agents — read-only fleet visibility (PM2/nginx/Docker/git/cron) + tamper-evident audit log + policy-as-code hooks. The ops + compliance layer Claude Code can't grow natively.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|