@topy-ai/maggie 0.7.59 → 0.7.60

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-zh-TW.md CHANGED
@@ -143,7 +143,7 @@ structure drift 或重複 treatment product 時 fail closed。
143
143
  deployment、memory、feedback 和 MaggieDash。內容先 draft/review,外部寫入、
144
144
  publish 與 production deployment 需要明確確認。
145
145
 
146
- 目前 npm 版本為 `0.7.59`,包含 fix-plan、public-check、Maggie Security、batch 31 排程 agent routines、報告收件匣與無人值守 agent 限制、PHP runtime 盤點與主機鎖、pull 網站改寫、query 點子與社群佇列檢查,batch 30 MaggieDash 先裝核心、release privacy gate、feedback 備援、社群連結與圖片檢查、大量頁面產生與 app 檢查,batch 29 預約規則、部署、app QA、助理與社群功能,以及 batch 28 產品 app、assistant tools、mobile、product release、skills catalog 與 bridge host 功能、batch 26、27 feedback 修正與 idempotent `maggie update`與 Booking email-template 合約/CLI validator 同步。本版完成 2026-09-24 booking feedback batch:Calendar grid/free-slot entry 與 host modal focus-restoration evidence。本版新增 Starter marketplace provisioning plan;本版完成 feedback batches 22、23:加入 declarative browser interaction evidence、design markup/style/content-key gate、compiler source anchoring、entity double-escape protection、`update --help` read-only、noindex hypothetical indexability、可過期 baseline acknowledgement、DOM-only link extraction regression,以及 MaggieDash 0.2.10 的 content override、短期 browser session、CDN-safe public-session cache contracts。authentication 和 isolated dev server 仍由 host 負責。`maggie-booking` workflow、傳統 email/password、Stripe、Resend、public booking flow 及既有安全邊界維持不變;provider-bound video generation 與 transactional delivery 仍記錄在 issue #39,前一批延後功能仍在 issue #38,不會直接成為 active memory。0.7.33 記錄並審查一筆更正回饋;確認 0.7.32 已正確處理 batch index,沒有修改已驗證的 shared behavior。0.7.32 加入 feedback 一基索引支援、MaggieDash panel 的 source/freshness/error evidence、Consent Mode 與實際 write/no-op reconciliation、SEO baseline recapture、sitemap origin rebasing、content-diff scope、migration ledger reconciliation、deployment credential preflight、release provenance/runtime preflight、icon release gate、opt-in blog auto-publish gate,以及 least-privilege VPS deployer。也修復 top-level `maggie feedback` dispatcher parity。0.7.31 加入 update 差異摘要、atomic installer copy、subset install manifest merge,以及 inventory drift 時 doctor non-zero。0.7.30 補上 feedback tracking issue closeout gate 與 batch 14/15 audit ledger。0.7.29 修正 npm package landing page 使用英文 README;0.7.28 加入 versioned Gemini model policy、明確 fallback 與 provenance、bundled-first CLI
146
+ 目前 npm 版本為 `0.7.60`,包含 fix-plan、public-check、Maggie Security、batch 31 排程 agent routines、報告收件匣與無人值守 agent 限制、PHP runtime 盤點與主機鎖、pull 網站改寫、query 點子與社群佇列檢查,batch 30 MaggieDash 先裝核心、release privacy gate、feedback 備援、社群連結與圖片檢查、大量頁面產生與 app 檢查,batch 29 預約規則、部署、app QA、助理與社群功能,以及 batch 28 產品 app、assistant tools、mobile、product release、skills catalog 與 bridge host 功能、batch 26、27 feedback 修正與 idempotent `maggie update`與 Booking email-template 合約/CLI validator 同步。本版完成 2026-09-24 booking feedback batch:Calendar grid/free-slot entry 與 host modal focus-restoration evidence。本版新增 Starter marketplace provisioning plan;本版完成 feedback batches 22、23:加入 declarative browser interaction evidence、design markup/style/content-key gate、compiler source anchoring、entity double-escape protection、`update --help` read-only、noindex hypothetical indexability、可過期 baseline acknowledgement、DOM-only link extraction regression,以及 MaggieDash 0.2.10 的 content override、短期 browser session、CDN-safe public-session cache contracts。authentication 和 isolated dev server 仍由 host 負責。`maggie-booking` workflow、傳統 email/password、Stripe、Resend、public booking flow 及既有安全邊界維持不變;provider-bound video generation 與 transactional delivery 仍記錄在 issue #39,前一批延後功能仍在 issue #38,不會直接成為 active memory。0.7.33 記錄並審查一筆更正回饋;確認 0.7.32 已正確處理 batch index,沒有修改已驗證的 shared behavior。0.7.32 加入 feedback 一基索引支援、MaggieDash panel 的 source/freshness/error evidence、Consent Mode 與實際 write/no-op reconciliation、SEO baseline recapture、sitemap origin rebasing、content-diff scope、migration ledger reconciliation、deployment credential preflight、release provenance/runtime preflight、icon release gate、opt-in blog auto-publish gate,以及 least-privilege VPS deployer。也修復 top-level `maggie feedback` dispatcher parity。0.7.31 加入 update 差異摘要、atomic installer copy、subset install manifest merge,以及 inventory drift 時 doctor non-zero。0.7.30 補上 feedback tracking issue closeout gate 與 batch 14/15 audit ledger。0.7.29 修正 npm package landing page 使用英文 README;0.7.28 加入 versioned Gemini model policy、明確 fallback 與 provenance、bundled-first CLI
147
147
  dispatch、`maggie --version`、feedback batch review 聚合與重複偵測、marketplace enrichment evidence、booking
148
148
  worker/resolver evidence,以及 read-only migration preflight。它也包含 host-owned mobile app surface contract、signed-in
149
149
  camera-state QA、直接 Astro route resolution、correlated feedback batch,以及
package/README.md CHANGED
@@ -89,7 +89,9 @@ Maggie keeps the existing project foundation and asks for decisions before
89
89
  shared routes, analytics, or publishing boundaries change. The current
90
90
  package ships 23 installable skills and a local-first MaggieDash foundation.
91
91
 
92
- This package is `0.7.59`. It makes `maggie security host-audit` (the deep
92
+ This package is `0.7.60`. `maggie security fix-plan` now emits **runnable** nginx fixes: http-context directives (TLS protocols, `server_tokens`) go into a global `conf.d` drop-in, and server-context ones (deny dotfiles, `proxy_hide_header`) into a snippet file applied with a backed-up, `nginx -t`-validated, auto-reverting `include`.
93
+
94
+ The 0.7.59 release made `maggie security host-audit` (the deep
93
95
  lynis audit over SSH) robust on hosts where a storage test can stall: lynis runs
94
96
  in its own process group under a watchdog, and the bundled profile skips the ZFS
95
97
  storage/filesystem tests that hang, so the audit completes instead of timing out.
@@ -856,8 +858,8 @@ artifact schemas.
856
858
  Recommended upgrade sequence for the current release:
857
859
 
858
860
  ```bash
859
- npx @topy-ai/maggie@0.7.59 update --scope project --project . --force
860
- npx @topy-ai/maggie@0.7.59 cleanup --scope project --project .
861
+ npx @topy-ai/maggie@0.7.60 update --scope project --project . --force
862
+ npx @topy-ai/maggie@0.7.60 cleanup --scope project --project .
861
863
  ```
862
864
 
863
865
  Maintainers should pass npm credentials through the repository helper, never
@@ -15,6 +15,7 @@ from __future__ import annotations
15
15
  import argparse
16
16
  import json
17
17
  import re
18
+ import shlex
18
19
  from pathlib import Path
19
20
 
20
21
  import maggie_security_core as core
@@ -557,6 +558,71 @@ def fix_commands(action: dict) -> tuple[list[str], list[tuple[str, str]], list[s
557
558
  return commands, snippets, todos
558
559
 
559
560
 
561
+ # nginx directives valid in the http{} context can be dropped into conf.d; the
562
+ # rest (location/proxy/add_header) must live in a server{} block.
563
+ NGINX_HTTP_DIRECTIVES = {"ssl_protocols", "ssl_ciphers", "ssl_prefer_server_ciphers", "ssl_ecdh_curve",
564
+ "ssl_session_tickets", "ssl_session_timeout", "ssl_dhparam", "server_tokens"}
565
+ NGINX_FILE_RE = re.compile(r"(/etc/nginx/[\w./-]+\.conf)")
566
+
567
+
568
+ def nginx_fix_block(actions: list[dict]) -> tuple[list[str], list[str]]:
569
+ """Runnable nginx fixes: a global drop-in for http-context directives, and a
570
+ snippet file + a guarded, reversible `include` for server-context ones."""
571
+ http_dirs: list[tuple[str, dict]] = []
572
+ server_by_file: dict[str, list[str]] = {}
573
+ manual: list[dict] = []
574
+ for action in actions:
575
+ rem = action["lead"].get("remediation") or {}
576
+ snippets = [s.get("text", "").strip() for s in (rem.get("snippets") or []) if s.get("text")]
577
+ if not snippets:
578
+ manual.append(action)
579
+ continue
580
+ tp = (action["lead"].get("target") or {}).get("path") or ""
581
+ match = NGINX_FILE_RE.search(tp) or NGINX_FILE_RE.search(action["lead"].get("title", ""))
582
+ vfile = match.group(1) if match else None
583
+ for text in snippets:
584
+ name = text.split()[0] if text.split() else ""
585
+ if name in NGINX_HTTP_DIRECTIVES:
586
+ http_dirs.append((text, action))
587
+ elif vfile:
588
+ server_by_file.setdefault(vfile, [])
589
+ if text not in server_by_file[vfile]:
590
+ server_by_file[vfile].append(text)
591
+ else:
592
+ manual.append(action)
593
+ sh: list[str] = []
594
+ md: list[str] = []
595
+ if http_dirs:
596
+ directives = list(dict.fromkeys(d for d, _ in http_dirs))
597
+ fixes = "; ".join(dict.fromkeys(a["title"] for _, a in http_dirs))
598
+ body = "".join(d + "\n" for d in directives)
599
+ sh += [f"# Global TLS/hardening — fixes: {fixes}",
600
+ f"printf %s {shlex.quote(body)} | sudo tee /etc/nginx/conf.d/00-maggie-hardening.conf >/dev/null",
601
+ "sudo nginx -t && sudo systemctl reload nginx", ""]
602
+ md.append("- **nginx global hardening** → drop-in `/etc/nginx/conf.d/00-maggie-hardening.conf`: "
603
+ + ", ".join(f"`{d}`" for d in directives))
604
+ for vfile, directives in server_by_file.items():
605
+ stem = re.sub(r"[^\w.-]", "_", re.sub(r"\.conf$", "", vfile.rsplit("/", 1)[-1]))
606
+ snip = f"/etc/nginx/snippets/maggie-{stem}.conf"
607
+ heredoc = "\n".join(directives)
608
+ sh += [f"# Harden {vfile} (backs up, validates, auto-reverts on error)",
609
+ f"sudo tee {snip} >/dev/null <<'MAGGIE_SNIP'",
610
+ heredoc,
611
+ "MAGGIE_SNIP",
612
+ f"sudo cp -a {shlex.quote(vfile)} {shlex.quote(vfile + '.maggie.bak')}",
613
+ f"sudo sed -i -E '/^[[:space:]]*server[[:space:]]*\\{{[[:space:]]*$/a\\ include {snip};' {shlex.quote(vfile)}",
614
+ f"sudo nginx -t && sudo systemctl reload nginx || {{ echo 'nginx test failed — reverting'; "
615
+ f"sudo cp -a {shlex.quote(vfile + '.maggie.bak')} {shlex.quote(vfile)}; sudo systemctl reload nginx; }}", ""]
616
+ md.append(f"- **nginx vhost hardening** (`{vfile}` via `{snip}` + guarded include): "
617
+ + ", ".join(f"`{d}`" for d in directives))
618
+ for action in manual:
619
+ rem = action["lead"].get("remediation") or {}
620
+ sh += [f"# [{action['priority']}] {action['title']} — {action['why']}",
621
+ f"# TODO (manual): {rem.get('summary') or action['how']}", ""]
622
+ md.append(f"- **{action['title']}** — {rem.get('summary') or action['how']} _(manual)_")
623
+ return sh, md
624
+
625
+
560
626
  def fix_plan(ctx: core.Context) -> dict:
561
627
  args = ctx.args
562
628
  since = resolve_since(ctx, args.since)
@@ -597,6 +663,12 @@ def fix_plan(ctx: core.Context) -> dict:
597
663
  continue
598
664
  sh += [f"# =================== {label} ===================", f"# {note}", ""]
599
665
  md += [f"## {label}", f"_{note}_", ""]
666
+ if key == "web-server":
667
+ block_sh, block_md = nginx_fix_block(items)
668
+ sh += block_sh
669
+ md += block_md
670
+ total += len(items)
671
+ continue
600
672
  for action in items:
601
673
  total += 1
602
674
  sh.append(f"# [{action['priority']}] {action['title']} — {action['why']}")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topy-ai/maggie",
3
- "version": "0.7.59",
3
+ "version": "0.7.60",
4
4
  "description": "Install and manage Maggie Skills for AI coding agents",
5
5
  "license": "MIT",
6
6
  "type": "module",