@massu/core 1.15.0 → 1.15.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 CHANGED
@@ -4,6 +4,32 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
 
7
+ ## [1.15.2] - 2026-07-06
8
+
9
+ **CRITICAL production fix: the `validate-key` cloud edge function returned HTTP 500 on every real API key (deploy drift), silently downgrading every Enterprise/Pro customer to Free** (`plan-2026-07-06-validate-key-deploy-drift`). The DEPLOYED `validate-key` Supabase edge function was a stale bundle that never received the 2026-05-31 `compareSync` fix — it still called the async bcrypt `compare()`, which spawns a Web Worker the Supabase Edge Runtime forbids, so it threw → HTTP 500 on every real `ms_live_` key. `@massu/core`'s license path (`validateLicense`) treated the 500 as "Free", so every paid key silently resolved to Free (surfaced during git-safe-api-key dogfooding, 2026-07-05). The repo source was already correct; the fix redeploys it (wrong-key probe now returns 401, not 500) — **no customer key changes, no re-hashing, no bcrypt/WebCrypto re-engineering** (the cause was a missed deploy, not a library bug). Patch per semver: a bug fix with no API change. Incident: `docs/incidents/2026-07-06-validate-key-deploy-drift-500.md`.
10
+
11
+ ### Fixed
12
+
13
+ - **`validate-key` edge function 500'd on every real API key (deploy drift).** The live bundle (version 8, 2026-05-31) still imported the async `compare()` (Web-Worker → forbidden in the Supabase Edge Runtime → throw → HTTP 500) five weeks after `e7d67f6` fixed the repo source to route through `verifyApiKeyHash`/`compareSync`; the validate-key redeploy of that fix never actually landed. Verified from the deployed bundle via `supabase functions download`; blast radius confirmed = validate-key only (the other 6 API-key edge functions were already correct). Redeployed the correct source.
14
+ - **`massu login` / `massu doctor` reported "Free" when the license server had errored or was unreachable.** `validateLicense` now returns a `LicenseValidationOutcome` (`validated` / `rejected` / `server_error` / `network_error` / `grace` / `cache_fresh` / `no_endpoint` / `no_key`); `login` and `doctor` distinguish an authoritative Free from a "could not validate (server error / offline) — tier UNKNOWN" state, so a server 500 is never misreported as a Free downgrade (this masking is why the outage looked like "Free").
15
+
16
+ ### Added
17
+
18
+ - **CR-60: API-key edge functions MUST be deploy-verified (three-layer structural drift-prevention).** (1) A source drift-guard (`website/src/__tests__/edge-async-bcrypt-compare-drift.test.ts`, vitest, CI + pre-push) fails if any edge function imports or calls the async bcrypt `compare(` — hashing must route through `verifyApiKeyHash`/`compareSync`; catches a function bypassing the shared helper (which the Deno helper test cannot). (2) A canonical edge-deploy + post-deploy real-key smoke test (`scripts/massu-deploy-edge-functions.sh`) fails the deploy unless a known-good key validates (HTTP 200 + expected tier) and a wrong key returns 401 (`scripts/massu-deploy.sh` deploys only Vercel, so it could never have caught this). (3) A Guardian readiness watcher (`massu_validate_key_readiness_watcher`, hourly) POSTs a known-good key to the live gateway and fires CRITICAL on any 500 / non-200 / wrong tier — this class had zero alerting.
19
+
20
+ ## [1.15.1] - 2026-07-05
21
+
22
+ **Node 26 compatibility — native-module (better-sqlite3) ABI fix + Node-major CI matrix**. Restores massu on the now-default Node 26. `@massu/core` shipped a prebuilt `better-sqlite3` binary compiled for an older `NODE_MODULE_VERSION` (ABI) and declared `engines.node` `">=20.0.0 <26.0.0"`; when Homebrew's default Node became v26 (ABI 147), the native module failed to load (`NODE_MODULE_VERSION 127 ... requires 147`), breaking BOTH the license check and the memory database in every consumer repo — `npx @massu/core@1 doctor` reported UNHEALTHY. This bumps `better-sqlite3` `^12.6.2` → `^12.11.1` (which ships prebuilt ABI-147 binaries for macOS/Linux/Alpine/Windows, so `npx` consumers with no compiler still load it) and removes the artificial `<26.0.0` engines ceiling (now `>=20.0.0`). Verified end-to-end: the full sqlite-backed suite (2710 tests) + `doctor` HEALTHY on Node 26 AND Node 22 (previously-shipped ABI 127 — no regression). Patch per semver: a compatibility fix with no API change.
23
+
24
+ ### Fixed
25
+
26
+ - **better-sqlite3 native module fails to load on Node 26 (ABI 147).** Bumped `better-sqlite3` to `^12.11.1` (prebuilt ABI-147 binaries for every consumer platform) and widened `packages/core` + `@massu/adapter-rails` + `@massu/adapter-spring` `engines.node` to `>=20.0.0` (dropped the `<26.0.0` ceiling that excluded the new default Node). `checkNativeModules()` + `checkLicenseStatus()` in `massu doctor` now pass on Node 26 (Status: HEALTHY).
27
+ - **root `npm audit` → 0 findings.** Bumped `tsx` `^4.0.0` → `^4.23.0` (built on patched esbuild `~0.28.0`) and added a root `overrides` pin `esbuild` `^0.28.1`, deduping the dev/test tree onto esbuild 0.28.1 and closing GHSA-g7r4-m6w7-qqqr (esbuild dev-server file read, Windows-only; esbuild is a build/test-only dep — never in `@massu/core` `dependencies` nor any published artifact). `npm audit fix` resolved `tar` (GHSA-vmf3-w455-68vh, file smuggling) and `vite` (GHSA-v6wh-96g9-6wx3, high). All-severity closure: `npm audit` reports zero at repo root.
28
+
29
+ ### Added
30
+
31
+ - **CI Node-major matrix + hard gate (structural drift-prevention, CR-46).** `.github/workflows/ci.yml` `native-module` job runs a better-sqlite3 load assertion + the full sqlite-backed suite on Node `20 / 22 / 24 / 26 / latest` — the `latest` leg auto-tracks the newest release, so a FUTURE Node major that breaks the native-module ABI fails CI with no manual matrix edit. Fronted by a required `Native Module Gate` status check (`.github/rulesets/main-branch.json`). The class is pinned by `node-compat-drift-guard.test.ts` (native load + no-`<`-ceiling on `engines.node` + CI-guard-wired) and the ruleset allowlist mirror (`ruleset-parser.ts` ↔ `ruleset-context-coverage.mjs`). Closes the "single-Node CI never sees a new-major ABI break" gap that let this incident ship. Incident: `docs/incidents/2026-07-05-node-26-native-module-abi.md`.
32
+
7
33
  ## [1.15.0] - 2026-06-02
8
34
 
9
35
  **Enterprise auto-learning governance + signed audit export (`plan-2026-06-01-enterprise-governance-audit-export`)**. Generalizes the Phase-3 per-rule two-operator review into an org-level governance policy enforced at the server promotion chokepoint + role-aware RLS, and adds a cryptographically-signed compliance export. Enterprise orgs (`plan='cloud_enterprise'`) can now set a promotion policy — minimum promoter role (rank-compared, never lexicographic), N-of-M distinct-approver requirement, allowed destinations, and a tighten-only hardened-review flag — that `promoted_rule_upsert` enforces before any promotion applies; a promotion below threshold is held `pending` and excluded from every seat's pull cursor until enough distinct operators (each other than the promoter) approve it. The new signed audit export streams the org's full governance history (policy, approvals, promotions, revocations) as a single Ed25519-signed FLAT envelope (records carried as a `records_json` STRING so the signature covers every record — no nested-array forgery hole), verifiable offline against the bundled public key. The `audit-export` edge function is the SOLE signer (single-signer, CR-46) for both the programmatic `ms_live_` path (admin-scoped) and the dashboard path (which calls it server-side via a service-role bearer and holds no key). Backwards-compatible additive feature — off the Enterprise path, behavior is unchanged (`approval_state` defaults to `applied`) — minor per semver.
@@ -21,6 +47,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
21
47
 
22
48
  - `promoted_rule_upsert` re-defined (CREATE OR REPLACE of the 045 body + governance branch); `/sync` recognizes the new `pending_approval` status; `/promoted-rules` excludes `approval_state='pending'` rows from the differential-pull cursor.
23
49
 
50
+ ### Fixed
51
+
52
+ - **loop-controller mirror drift closed** (`plan-loop-controller-mirror-drift-closure`) — reconciled the 78-line preexisting drift between the canonical `.claude/commands/massu-loop/references/loop-controller.md` and its shipped mirror `packages/core/commands/massu-loop/references/loop-controller.md`, and extended the byte-equivalence drift-guard (`auto-learning-mirror-drift-guard.test.ts`) to cover the loop-controller pair so the drift class is now structurally impossible for both command-reference mirrors. Docs-only; no API change.
53
+
24
54
  ## [1.14.0] - 2026-06-02
25
55
 
26
56
  **Curated Rule Packs — versioned, installable, actually-enforced (`plan-2026-06-01-curated-rule-packs`)**. Closes the inert-marketplace bug class: the rule-pack marketplace existed but enforced nothing — installing a pack flattened its rules into `org_rules`, which no core enforcement path ever read. Now an installed pack's rules materialize on the developer's machine as Ed25519-signed, provenance-tagged rule candidates that a human reviews and approves through `/massu-rule packs` (packs **propose**, humans **approve** — CR-39; no fake "active"/"enforced" state). Pack rules ride the existing `applyRuleCandidate()` chokepoint with the same Team-gated, signature-verified trust model as team-shared promotion (CR-54/55/57); executable destinations (`pattern-scanner`/`custom-destination`) route through the hardened two-operator review path and never auto-enforce. Ships the versioning + curation workflow (SemVer monotonicity, an immutable `rule_pack_versions` history, a `rule_pack_publish` SECURITY DEFINER RPC) the marketplace previously lacked. Backwards-compatible additive feature — new `/massu-rule packs` subcommand + `pack` provenance origin, zero breaking changes — minor per semver.
@@ -31,12 +31,21 @@ This command is a **loop controller** for implementation + verification. Your jo
31
31
 
32
32
  ### Agent Result Persistence
33
33
 
34
- All Task sub-agents MUST write their results to disk in addition to returning text:
35
- - Security review: `.massu/agent-results/{timestamp}-security.json`
36
- - Architecture review: `.massu/agent-results/{timestamp}-architecture.json`
37
- - Verification audit: `.massu/agent-results/{timestamp}-verify-{iteration}.json`
34
+ All Task sub-agents MUST write their results to disk in addition to returning text. Two naming conventions are accepted by the completion gate (CR-52 / `scripts/massu-loop-completion-gate.sh`):
38
35
 
39
- JSON format: `{ iteration, gaps_discovered, gaps_fixed, gaps_remaining, plan_items_total, plan_items_verified, findings: [] }`
36
+ **NEW convention (preferred, plan-token-namespaced)**:
37
+ - `.massu/agent-results/<plan-token>-post-impl-security-<iso>.json`
38
+ - `.massu/agent-results/<plan-token>-post-impl-architecture-<iso>.json`
39
+ - `.massu/agent-results/<plan-token>-post-impl-pattern-<iso>.json`
40
+ - `.massu/agent-results/<plan-token>-post-impl-ux-<iso>.json` (loop-playwright only)
41
+ - Verification audit: `.massu/agent-results/<plan-token>-verify-iter<iteration>-<iso>.json`
42
+
43
+ **LEGACY convention (still valid, accepted via filename + mtime ≥ loop-start)**:
44
+ - `.massu/agent-results/{timestamp}-security.json`
45
+ - `.massu/agent-results/{timestamp}-architecture.json`
46
+ - `.massu/agent-results/{timestamp}-verify-{iteration}.json`
47
+
48
+ JSON format: `{ plan_token, reviewer_type, timestamp, iteration, gaps_discovered, gaps_fixed, gaps_remaining, plan_items_total, plan_items_verified, findings: [] }`
40
49
 
41
50
  This prevents context overflow from killing verification progress. If the parent session crashes, a new session can read these files via `bash scripts/hooks/read-agent-results.sh` to resume.
42
51
 
@@ -53,8 +62,17 @@ At completion, write a completion entry.
53
62
 
54
63
  ```
55
64
  PLAN_PATH = $ARGUMENTS (the plan file path or task description)
65
+ PLAN_TOKEN = extract `**Plan Token**:` value from PLAN_PATH header (used by Phase 0.5 / 2.2)
66
+ # Interpolation contract: `${PLAN_TOKEN}` references in the snippets below are
67
+ # substituted by the agent at protocol-interpretation time (NOT shell-substituted
68
+ # inside a script). The PLAN_TOKEN value is validated by
69
+ # scripts/lib/loop-completion-helpers.sh:plan_token_strict_check before any
70
+ # script call (rejects newlines, whitespace, and degenerate tokens).
56
71
  iteration = 0
57
72
 
73
+ # Phase 0.5: Record loop-start timestamp (consumed by Phase 2.2 completion gate, CR-52)
74
+ bash -c 'source scripts/lib/loop-completion-helpers.sh && loop_start_record "${PLAN_TOKEN}"'
75
+
58
76
  # Phase 1: IMPLEMENT (do the work)
59
77
  # Read plan, extract items, implement each one with VR-* proof
60
78
 
@@ -62,17 +80,34 @@ iteration = 0
62
80
  # Spawn focused review subagents IN PARALLEL for independent analysis
63
81
  # Each reviewer has an adversarial mindset and a SINGLE focused concern (Principle #20)
64
82
  # Elegance/simplicity assessment happens in Phase 2.1 POST-BUILD REFLECTION (Q4)
83
+ #
84
+ # CR-52: Named reviewers REQUIRED (consolidated with golden-path/phase-2-implementation.md).
85
+ # Each reviewer MUST write evidence JSON to:
86
+ # .massu/agent-results/${PLAN_TOKEN}-post-impl-<reviewer-type>-<iso>.json
87
+ # before returning. The Phase 2.2 completion gate validates evidence existence.
65
88
 
66
- security_result = Task(subagent_type="general-purpose", model="opus", prompt="
89
+ security_result = Task(subagent_type="massu-security-reviewer", model="opus", prompt="
67
90
  Review implementation for plan: {PLAN_PATH}
68
91
  Focus: Security vulnerabilities, auth gaps, input validation, data exposure
69
92
  Check all new/modified files. Return structured result with SECURITY_GATE.
93
+ CR-52: Write evidence to .massu/agent-results/${PLAN_TOKEN}-post-impl-security-<iso>.json
94
+ with fields {plan_token, reviewer_type:'security', timestamp, gaps_discovered, gaps_fixed, findings:[]}
70
95
  ")
71
96
 
72
- architecture_result = Task(subagent_type="general-purpose", model="opus", prompt="
97
+ architecture_result = Task(subagent_type="massu-architecture-reviewer", model="opus", prompt="
73
98
  Review implementation for plan: {PLAN_PATH}
74
99
  Focus: Design issues, coupling problems, pattern compliance, scalability
75
100
  Check all new/modified files. Return structured result with ARCHITECTURE_GATE.
101
+ CR-52: Write evidence to .massu/agent-results/${PLAN_TOKEN}-post-impl-architecture-<iso>.json
102
+ with fields {plan_token, reviewer_type:'architecture', timestamp, gaps_discovered, gaps_fixed, findings:[]}
103
+ ")
104
+
105
+ pattern_result = Task(subagent_type="massu-pattern-reviewer", model="sonnet", prompt="
106
+ Review implementation for plan: {PLAN_PATH}
107
+ Focus: Code quality, ESM compliance, config-driven patterns, TypeScript strict mode, test coverage
108
+ Check all new/modified files. Return structured result with PATTERN_GATE.
109
+ CR-52: Write evidence to .massu/agent-results/${PLAN_TOKEN}-post-impl-pattern-<iso>.json
110
+ with fields {plan_token, reviewer_type:'pattern', timestamp, gaps_discovered, gaps_fixed, findings:[]}
76
111
  ")
77
112
 
78
113
  # Parse results and fix ALL findings at ALL severity levels (CR-45)
@@ -159,6 +194,17 @@ END WHILE
159
194
 
160
195
  # Phase 2.1: POST-BUILD REFLECTION + MANDATORY MEMORY PERSIST (CR-38)
161
196
  # See references/auto-learning.md for full protocol
197
+
198
+ # Phase 2.2: COMPLETION GATE (STRUCTURAL — CR-52)
199
+ # AFTER Phase 2.1 POST-BUILD REFLECTION completes, but BEFORE returning the
200
+ # final report. Non-zero exit BLOCKS the loop from declaring success.
201
+ bash scripts/massu-loop-completion-gate.sh "${PLAN_TOKEN}" || {
202
+ echo "BLOCKED: Phase 1.5 evidence missing for ${PLAN_TOKEN}"
203
+ echo "Spawn at least one named reviewer subagent and ensure evidence JSON is written"
204
+ echo "to .massu/agent-results/${PLAN_TOKEN}-post-impl-*.json before retrying."
205
+ echo "Bypass (audit-trail logged): MASSU_SKIP_COMPLETION_GATE=1"
206
+ exit 1
207
+ }
162
208
  ```
163
209
 
164
210
  ### Rules for the Loop Controller
@@ -175,6 +221,7 @@ END WHILE
175
221
  | **ALWAYS run multi-perspective review after implementation** | Multiple reviewers catch different issues than 1 auditor |
176
222
  | **Run review subagents IN PARALLEL** | Security and architecture reviews are independent |
177
223
  | **Fix CRITICAL/HIGH findings before verification** | Don't waste auditor passes on known issues |
224
+ | **Phase 2.2 completion gate is STRUCTURAL** | `bash scripts/massu-loop-completion-gate.sh` — non-zero exit BLOCKS mark-complete (CR-52). Silent self-attestation is replaced by evidence-file existence check. |
178
225
 
179
226
  ### Why This Architecture Exists
180
227