@topy-ai/maggie 0.7.54 → 0.7.56

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.
Files changed (104) hide show
  1. package/README-zh-TW.md +25 -23
  2. package/README.md +93 -71
  3. package/bin/maggie.js +14 -2
  4. package/bundled-contracts/maggie-assistant-tools/booking-receptionist-example-v1.json +18 -2
  5. package/bundled-contracts/maggie-assistant-tools/report-v1.schema.json +43 -0
  6. package/bundled-contracts/maggie-assistant-tools/tool-registry-example-v1.json +249 -11
  7. package/bundled-contracts/maggie-assistant-tools/tool-registry-v1.schema.json +175 -0
  8. package/bundled-contracts/maggie-deployment/readiness-v1.schema.json +2 -1
  9. package/bundled-contracts/maggie-ops/agent-routines-v1.schema.json +48 -0
  10. package/bundled-contracts/maggie-security/finding-example-v1.json +89 -0
  11. package/bundled-contracts/maggie-security/finding-v1.schema.json +63 -0
  12. package/bundled-contracts/maggie-security/findings-set-example-v1.json +148 -0
  13. package/bundled-contracts/maggie-security/findings-set-v1.schema.json +32 -0
  14. package/bundled-contracts/maggie-security/protect-plan-v1.schema.json +28 -0
  15. package/bundled-contracts/maggie-security/report-v1.schema.json +29 -0
  16. package/bundled-contracts/maggie-security/stack-example-v1.json +66 -0
  17. package/bundled-contracts/maggie-security/stack-upload-v1.schema.json +22 -0
  18. package/bundled-contracts/maggie-security/stack-v1.schema.json +37 -0
  19. package/bundled-contracts/maggie-security/tools-lock-v1.schema.json +36 -0
  20. package/bundled-skills/catalog.json +5 -1
  21. package/bundled-skills/maggie-assistant-tools/SKILL.md +34 -1
  22. package/bundled-skills/maggie-assistant-tools/references/report-inbox.md +45 -0
  23. package/bundled-skills/maggie-assistant-tools/references/unattended-agents.md +70 -0
  24. package/bundled-skills/maggie-blog/SKILL.md +9 -2
  25. package/bundled-skills/maggie-booking/SKILL.md +1 -1
  26. package/bundled-skills/maggie-dash/SKILL.md +9 -0
  27. package/bundled-skills/maggie-deployment/SKILL.md +77 -1
  28. package/bundled-skills/maggie-deployment/references/vps.md +5 -0
  29. package/bundled-skills/maggie-marketplace/SKILL.md +21 -1
  30. package/bundled-skills/maggie-ops/SKILL.md +28 -0
  31. package/bundled-skills/maggie-ops/references/agents-repository.md +108 -0
  32. package/bundled-skills/maggie-ops/references/ops-autopilot.md +65 -0
  33. package/bundled-skills/maggie-ops/references/routine-mode.md +92 -0
  34. package/bundled-skills/maggie-security/SKILL.md +172 -0
  35. package/bundled-skills/maggie-security/agents/openai.yaml +4 -0
  36. package/bundled-skills/maggie-security/data/LICENSE-NOTICE.md +24 -0
  37. package/bundled-skills/maggie-security/data/asvs-map.json +209 -0
  38. package/bundled-skills/maggie-security/data/fail2ban/filter.d/maggie-wordpress.conf +6 -0
  39. package/bundled-skills/maggie-security/data/semgrep/LICENSE-NOTICE.md +5 -0
  40. package/bundled-skills/maggie-security/data/semgrep/VERSION +1 -0
  41. package/bundled-skills/maggie-security/data/semgrep/rules/dockerfile.yaml +14 -0
  42. package/bundled-skills/maggie-security/data/semgrep/rules/generic.yaml +26 -0
  43. package/bundled-skills/maggie-security/data/semgrep/rules/js.yaml +216 -0
  44. package/bundled-skills/maggie-security/data/semgrep/rules/php-debug-ok.yaml +17 -0
  45. package/bundled-skills/maggie-security/data/semgrep/rules/php-debug.yaml +17 -0
  46. package/bundled-skills/maggie-security/data/semgrep/rules/php.yaml +101 -0
  47. package/bundled-skills/maggie-security/data/semgrep/tests/dockerfile.dockerfile +10 -0
  48. package/bundled-skills/maggie-security/data/semgrep/tests/generic.astro +11 -0
  49. package/bundled-skills/maggie-security/data/semgrep/tests/generic.conf +11 -0
  50. package/bundled-skills/maggie-security/data/semgrep/tests/js.jsx +95 -0
  51. package/bundled-skills/maggie-security/data/semgrep/tests/php-debug-ok.php +5 -0
  52. package/bundled-skills/maggie-security/data/semgrep/tests/php-debug.php +3 -0
  53. package/bundled-skills/maggie-security/data/semgrep/tests/php.php +55 -0
  54. package/bundled-skills/maggie-security/evals/evals.json +97 -0
  55. package/bundled-skills/maggie-security/references/commands.md +111 -0
  56. package/bundled-skills/maggie-security/references/cve-response.md +24 -0
  57. package/bundled-skills/maggie-security/references/explaining-findings.md +57 -0
  58. package/bundled-skills/maggie-security/references/findings.md +39 -0
  59. package/bundled-skills/maggie-security/references/ownership-and-consent.md +29 -0
  60. package/bundled-skills/maggie-security/references/site-types.md +22 -0
  61. package/bundled-skills/maggie-security/references/tools-and-licences.md +16 -0
  62. package/bundled-skills/maggie-security/references/workflows.md +23 -0
  63. package/bundled-skills/maggie-security/registry/security-tools.registry.json +628 -0
  64. package/bundled-skills/maggie-security/routines.example.json +27 -0
  65. package/bundled-skills/maggie-seo-geo/SKILL.md +9 -1
  66. package/bundled-skills/maggie-social-share/SKILL.md +20 -0
  67. package/bundled-tools/clis/maggie.py +63 -3
  68. package/bundled-tools/clis/maggie_assistant_tools.py +225 -1
  69. package/bundled-tools/clis/maggie_deployment_readiness.py +17 -2
  70. package/bundled-tools/clis/maggie_host_runtime.py +458 -0
  71. package/bundled-tools/clis/maggie_live_urls.py +11 -2
  72. package/bundled-tools/clis/maggie_ops.py +2 -0
  73. package/bundled-tools/clis/maggie_ops_routines.py +352 -0
  74. package/bundled-tools/clis/maggie_query_ideas.py +154 -0
  75. package/bundled-tools/clis/maggie_security.py +342 -0
  76. package/bundled-tools/clis/maggie_security_agent.py +326 -0
  77. package/bundled-tools/clis/maggie_security_code.py +650 -0
  78. package/bundled-tools/clis/maggie_security_core.py +1512 -0
  79. package/bundled-tools/clis/maggie_security_deps.py +560 -0
  80. package/bundled-tools/clis/maggie_security_health.py +415 -0
  81. package/bundled-tools/clis/maggie_security_host.py +511 -0
  82. package/bundled-tools/clis/maggie_security_hosted.py +115 -0
  83. package/bundled-tools/clis/maggie_security_intel.py +1294 -0
  84. package/bundled-tools/clis/maggie_security_inventory.py +1023 -0
  85. package/bundled-tools/clis/maggie_security_logs.py +777 -0
  86. package/bundled-tools/clis/maggie_security_mcp.py +473 -0
  87. package/bundled-tools/clis/maggie_security_mirror.py +122 -0
  88. package/bundled-tools/clis/maggie_security_protect.py +519 -0
  89. package/bundled-tools/clis/maggie_security_report.py +506 -0
  90. package/bundled-tools/clis/maggie_security_standards.py +214 -0
  91. package/bundled-tools/clis/maggie_security_versions.py +381 -0
  92. package/bundled-tools/clis/maggie_security_web.py +936 -0
  93. package/bundled-tools/clis/maggie_skill_catalog.py +16 -2
  94. package/bundled-tools/clis/maggie_social_share.py +101 -1
  95. package/bundled-tools/clis/maggie_version_sources.py +93 -0
  96. package/bundled-tools/clis/security_data/eol-snapshot.json +1 -0
  97. package/bundled-tools/clis/security_data/gitleaks-rules.json +3812 -0
  98. package/bundled-tools/clis/security_data/maltrail-lists.json +1 -0
  99. package/bundled-tools/clis/security_data/public-suffix-icann.txt +7374 -0
  100. package/bundled-tools/clis/security_data/retire-extractors.json +695 -0
  101. package/bundled-tools/clis/security_data/sigma-web.json +6514 -0
  102. package/bundled-tools/clis/security_data/tools.lock.json +358 -0
  103. package/bundled-tools/integrations/maggie-api-pull.md +28 -1
  104. package/package.json +1 -1
@@ -0,0 +1,148 @@
1
+ {
2
+ "schema": "maggie-security-findings.v1",
3
+ "run": {
4
+ "id": "2026-10-24T06:17:03Z-deps-3f9a",
5
+ "command": "deps",
6
+ "maggie_version": "0.7.55",
7
+ "started_at": "2026-10-24T06:17:41Z",
8
+ "finished_at": "2026-10-24T06:17:41Z",
9
+ "site": "example-site",
10
+ "inputs": {
11
+ "lockfile": "package-lock.json"
12
+ },
13
+ "sources": [
14
+ {
15
+ "id": "osv-api",
16
+ "status": "ok",
17
+ "fetched_at": "2026-10-24T06:17:09Z"
18
+ }
19
+ ],
20
+ "tools": [
21
+ {
22
+ "name": "osv-scanner",
23
+ "version": "2.2.3",
24
+ "sha256": null
25
+ }
26
+ ],
27
+ "degraded": [],
28
+ "refused": [],
29
+ "covered": [
30
+ "pkg:npm/next"
31
+ ]
32
+ },
33
+ "summary": {
34
+ "new": 1,
35
+ "open": 0,
36
+ "fixed": 0,
37
+ "by_severity": {
38
+ "critical": 1,
39
+ "high": 0,
40
+ "medium": 0,
41
+ "low": 0,
42
+ "info": 0
43
+ },
44
+ "by_priority": {
45
+ "p0": 1,
46
+ "p1": 0,
47
+ "p2": 0,
48
+ "p3": 0,
49
+ "p4": 0
50
+ }
51
+ },
52
+ "clipped": {
53
+ "findings": false,
54
+ "total": 1
55
+ },
56
+ "findings": [
57
+ {
58
+ "schema": "maggie-security-finding.v1",
59
+ "id": "msf_a6f3541c959e767b53b29ad6",
60
+ "kind": "vulnerability",
61
+ "title": "next 14.2.10: authorization bypass in middleware",
62
+ "severity": "critical",
63
+ "severity_source": "cvss",
64
+ "priority": "p0",
65
+ "confidence": "likely",
66
+ "aliases": [
67
+ "CVE-2025-29927",
68
+ "GHSA-f82v-jwr5-mffw"
69
+ ],
70
+ "cvss": {
71
+ "version": "3.1",
72
+ "score": 9.1,
73
+ "vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N"
74
+ },
75
+ "epss": {
76
+ "score": 0.93,
77
+ "percentile": 0.99,
78
+ "date": "2026-10-23"
79
+ },
80
+ "kev": {
81
+ "listed": true,
82
+ "date_added": "2025-04-02",
83
+ "ransomware": "unknown"
84
+ },
85
+ "cwe_ids": [
86
+ "CWE-285"
87
+ ],
88
+ "asvs_ids": [
89
+ "V8.2.1"
90
+ ],
91
+ "affected": {
92
+ "purl": "pkg:npm/next@14.2.10",
93
+ "ecosystem": "npm",
94
+ "name": "next",
95
+ "version": "14.2.10",
96
+ "component_type": "library",
97
+ "direct": true,
98
+ "scope": "runtime"
99
+ },
100
+ "fix": {
101
+ "fixed_versions": [
102
+ "14.2.25"
103
+ ],
104
+ "recommended": "14.2.25",
105
+ "available": true
106
+ },
107
+ "target": {
108
+ "site": "example-site",
109
+ "host": null,
110
+ "url": null,
111
+ "path": "package-lock.json",
112
+ "image": null
113
+ },
114
+ "evidence": [
115
+ {
116
+ "path": "package-lock.json",
117
+ "line": 812,
118
+ "excerpt": "\"next\": \"14.2.10\""
119
+ }
120
+ ],
121
+ "source": {
122
+ "command": "deps",
123
+ "tool": "osv-scanner",
124
+ "tool_version": "2.2.3",
125
+ "rule_id": "GHSA-f82v-jwr5-mffw",
126
+ "feed": "osv",
127
+ "fetched_at": "2026-10-24T06:17:09Z"
128
+ },
129
+ "remediation": {
130
+ "summary": "Upgrade next to 14.2.25 or later.",
131
+ "steps": [
132
+ "npm install next@14.2.25",
133
+ "rebuild and redeploy"
134
+ ],
135
+ "snippets": [],
136
+ "references": [
137
+ "https://osv.dev/vulnerability/GHSA-f82v-jwr5-mffw"
138
+ ],
139
+ "cheat_sheet": null
140
+ },
141
+ "signal": null,
142
+ "status": "new",
143
+ "first_seen": "2026-10-24T06:17:41Z",
144
+ "last_seen": "2026-10-24T06:17:41Z"
145
+ }
146
+ ],
147
+ "fixed": []
148
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://maggie.noblox.app/contracts/maggie-security/findings-set-v1.json",
4
+ "title": "Maggie security findings set",
5
+ "description": "One run of a maggie security command. findings[] items follow finding-v1.schema.json.",
6
+ "type": "object",
7
+ "required": ["schema", "run", "summary", "clipped", "findings"],
8
+ "properties": {
9
+ "schema": {"const": "maggie-security-findings.v1"},
10
+ "run": {"type": "object", "required": ["id", "command", "started_at", "finished_at", "sources", "tools", "degraded", "refused"], "properties": {
11
+ "id": {"type": "string"}, "command": {"type": "string"}, "maggie_version": {"type": "string"},
12
+ "started_at": {"type": "string"}, "finished_at": {"type": "string"}, "site": {"type": ["string", "null"]},
13
+ "inputs": {"type": "object"},
14
+ "sources": {"type": "array", "items": {"type": "object", "required": ["id", "status"], "properties": {
15
+ "id": {"type": "string"}, "status": {"enum": ["ok", "cached", "degraded", "skipped"]}, "fetched_at": {"type": ["string", "null"]},
16
+ "version": {"type": ["string", "null"]}, "cursor": {"type": ["string", "null"]}, "error": {"type": ["string", "null"]}
17
+ }}},
18
+ "tools": {"type": "array", "items": {"type": "object", "required": ["name"], "properties": {"name": {"type": "string"}, "version": {"type": ["string", "null"]}, "sha256": {"type": ["string", "null"]}}}},
19
+ "degraded": {"type": "array", "items": {"type": "string"}},
20
+ "refused": {"type": "array", "items": {"type": "string"}},
21
+ "covered": {"type": "array", "items": {"type": "string"}, "description": "Targets this run fully covered; the ledger only marks findings on these targets fixed."}
22
+ }},
23
+ "summary": {"type": "object", "required": ["new", "open", "fixed", "by_severity"], "properties": {
24
+ "new": {"type": "integer"}, "open": {"type": "integer"}, "fixed": {"type": "integer"},
25
+ "by_severity": {"type": "object", "properties": {"critical": {"type": "integer"}, "high": {"type": "integer"}, "medium": {"type": "integer"}, "low": {"type": "integer"}, "info": {"type": "integer"}}},
26
+ "by_priority": {"type": "object"}
27
+ }},
28
+ "clipped": {"type": "object", "required": ["findings", "total"], "properties": {"findings": {"type": "boolean"}, "total": {"type": "integer"}}},
29
+ "findings": {"type": "array", "items": {"type": "object"}},
30
+ "fixed": {"type": "array", "items": {"type": "string"}, "description": "Finding ids the ledger marked fixed in this run."}
31
+ }
32
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://maggie.noblox.app/contracts/maggie-security/protect-plan-v1.json",
4
+ "title": "Maggie security protection plan",
5
+ "description": "A reviewed, never auto-applied plan from `maggie security protect-plan`. See docs/maggie-security/05-protection-waf-prd.md section 6.2.",
6
+ "type": "object",
7
+ "required": ["schema", "id", "host", "created_at", "engine", "egress", "data_sharing", "requires", "risk_notes", "steps", "verify", "rollback"],
8
+ "properties": {
9
+ "schema": {"const": "maggie-security-protect-plan.v1"},
10
+ "id": {"type": "string", "pattern": "^pp_"},
11
+ "host": {"type": "string"},
12
+ "created_at": {"type": "string"},
13
+ "engine": {"enum": ["crowdsec", "fail2ban", "cloudflare"]},
14
+ "waf": {"type": "object"},
15
+ "inputs": {"type": "object"},
16
+ "egress": {"type": "array", "items": {"type": "object", "required": ["host", "why"]}},
17
+ "data_sharing": {"type": "object", "required": ["crowdsec_capi", "console"], "properties": {"crowdsec_capi": {"type": "boolean"}, "console": {"const": false}}},
18
+ "requires": {"type": "object", "required": ["consent"], "properties": {"consent": {"const": "host-change"}}},
19
+ "risk_notes": {"type": "array", "items": {"type": "string"}},
20
+ "advice": {"type": "array", "items": {"type": "string"}},
21
+ "steps": {"type": "array", "items": {"type": "object", "required": ["n", "title", "run", "kind", "reversible"], "properties": {
22
+ "n": {"type": "integer"}, "title": {"type": "string"}, "run": {"type": "string"}, "kind": {"enum": ["local", "host"]},
23
+ "reversible": {"type": "boolean"}, "rollback": {"type": "string"}}}},
24
+ "verify": {"type": "array", "items": {"type": "object", "required": ["check", "expect"]}},
25
+ "rollback": {"type": "array", "items": {"type": "string"}},
26
+ "allowlist": {"type": "object"}
27
+ }
28
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://maggie.noblox.app/contracts/maggie-security/report-v1.json",
4
+ "title": "Maggie security report",
5
+ "description": "Per-site report built by `maggie security report`; references finding ids, full findings stay in .maggie/security/runs/. See docs/maggie-security/09-risk-report-standards-prd.md section 8.2.",
6
+ "type": "object",
7
+ "required": ["schema", "id", "site", "kind", "period", "verdict", "counts", "actions", "checked", "degraded_sources", "runs", "findings"],
8
+ "properties": {
9
+ "schema": {"const": "maggie-security-report.v1"},
10
+ "id": {"type": "string"},
11
+ "site": {"type": "string"},
12
+ "kind": {"enum": ["weekly", "daily_ops", "incident", "gate"]},
13
+ "audience": {"enum": ["owner", "technical"]},
14
+ "period": {"type": "object", "required": ["from", "to"], "properties": {"from": {"type": "string"}, "to": {"type": "string"}}},
15
+ "verdict": {"type": "object", "required": ["code", "text"], "properties": {"code": {"enum": ["possible-break-in", "act-today", "act-this-week", "nothing-urgent"]}, "text": {"type": "string"}}},
16
+ "counts": {"type": "object", "required": ["new", "open", "fixed", "by_priority"]},
17
+ "actions": {"type": "array", "items": {"type": "object", "required": ["finding_id", "priority", "title"]}},
18
+ "coverage": {"type": ["object", "null"]},
19
+ "checked": {"type": "array", "items": {"type": "object", "required": ["command", "last_run", "degraded"]}},
20
+ "not_checked": {"type": "array", "items": {"type": "string"}},
21
+ "degraded_sources": {"type": "array", "items": {"type": "string"}},
22
+ "runs": {"type": "array", "items": {"type": "string"}},
23
+ "findings": {"type": "array", "items": {"type": "string", "pattern": "^msf_[0-9a-f]{24}$"}},
24
+ "fixed": {"type": "array", "items": {"type": "string"}},
25
+ "maggie_version": {"type": "string"},
26
+ "incident": {"type": "object", "required": ["id", "title", "status", "timeline"]},
27
+ "gate": {"type": "object", "required": ["decision", "block", "warn"], "properties": {"decision": {"enum": ["pass", "warn", "block"]}, "block": {"type": "array"}, "warn": {"type": "array"}, "checked": {"type": "array"}}}
28
+ }
29
+ }
@@ -0,0 +1,66 @@
1
+ {
2
+ "schema": "maggie-security-stack.v1",
3
+ "site": {
4
+ "id": "example-site",
5
+ "type": "node-app",
6
+ "domains": [
7
+ "example.com"
8
+ ],
9
+ "hosting": "vps-with-cloudflare-dns"
10
+ },
11
+ "collected_at": "2026-10-24T06:00:00Z",
12
+ "hash": "sha256:73a805dca6155476f3cdc7f91b1954517325abcda06ecbb381d550c4732cc497",
13
+ "sources": [
14
+ {
15
+ "kind": "lockfile",
16
+ "path": "package-lock.json"
17
+ },
18
+ {
19
+ "kind": "runtime-inventory",
20
+ "path": ".maggie/security/inventory/host-web1.json"
21
+ }
22
+ ],
23
+ "components": [
24
+ {
25
+ "purl": "pkg:npm/next@14.2.10",
26
+ "ecosystem": "npm",
27
+ "name": "next",
28
+ "version": "14.2.10",
29
+ "scope": "runtime",
30
+ "direct": true,
31
+ "location": "package-lock.json"
32
+ }
33
+ ],
34
+ "runtimes": [
35
+ {
36
+ "name": "node",
37
+ "version": "20.11.1",
38
+ "cycle": "20",
39
+ "host": "web1",
40
+ "source": "runtime-inventory"
41
+ },
42
+ {
43
+ "name": "nginx",
44
+ "version": "1.24.0",
45
+ "cycle": "1.24",
46
+ "host": "web1",
47
+ "source": "runtime-inventory"
48
+ }
49
+ ],
50
+ "wordpress": null,
51
+ "images": [],
52
+ "hosts": [
53
+ {
54
+ "id": "web1",
55
+ "os": "ubuntu 22.04",
56
+ "public": true
57
+ }
58
+ ],
59
+ "watch": {
60
+ "products": [
61
+ "nginx",
62
+ "node",
63
+ "next"
64
+ ]
65
+ }
66
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://maggie.noblox.app/contracts/maggie-security/stack-upload-v1.json",
4
+ "title": "Maggie security stack upload",
5
+ "description": "What `maggie security inventory --export-upload` sends to CMO.so for the hosted daily watch: package and runtime names and versions only. No file paths, host names, lockfile contents, logs or secrets. See docs/maggie-security/11-mcp-tools-prd.md section 9.",
6
+ "type": "object",
7
+ "required": ["schema", "workspace", "site_type", "created_at", "hash", "components", "runtimes"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "schema": {"const": "maggie-security-stack-upload.v1"},
11
+ "workspace": {"type": "string", "maxLength": 253},
12
+ "site_type": {"type": "string"},
13
+ "created_at": {"type": "string"},
14
+ "hash": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"},
15
+ "components": {"type": "array", "maxItems": 20000, "items": {"type": "object", "required": ["ecosystem", "name", "version"], "additionalProperties": false,
16
+ "properties": {"ecosystem": {"type": "string"}, "name": {"type": "string"}, "version": {"type": "string"}, "scope": {"type": "string"}, "direct": {"type": ["boolean", "null"]}}}},
17
+ "runtimes": {"type": "array", "items": {"type": "object", "required": ["name", "version"], "additionalProperties": false,
18
+ "properties": {"name": {"type": "string"}, "version": {"type": "string"}, "host": {"type": ["string", "null"], "description": "opaque alias such as web1, never a hostname"}}}},
19
+ "wordpress": {"type": ["object", "null"]},
20
+ "watch": {"type": "array", "items": {"type": "string"}}
21
+ }
22
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://maggie.noblox.app/contracts/maggie-security/stack-v1.json",
4
+ "title": "Maggie security stack inventory",
5
+ "description": "What a site actually runs; read by every matcher. See docs/maggie-security/00-foundation-prd.md section 8.",
6
+ "type": "object",
7
+ "required": ["schema", "site", "collected_at", "hash", "sources", "components", "runtimes"],
8
+ "properties": {
9
+ "schema": {"const": "maggie-security-stack.v1"},
10
+ "site": {"type": "object", "required": ["id"], "properties": {
11
+ "id": {"type": "string"}, "type": {"enum": ["static", "wordpress", "node-app", "php-app", "python-app", "java-app", "go-app", "ruby-app", "dotnet-app", "astro", "workers", "unknown"]},
12
+ "domains": {"type": "array", "items": {"type": "string"}}, "hosting": {"type": ["string", "null"]}
13
+ }},
14
+ "collected_at": {"type": "string"},
15
+ "hash": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"},
16
+ "sources": {"type": "array", "items": {"type": "object", "required": ["kind", "path"], "properties": {
17
+ "kind": {"enum": ["lockfile", "manifest", "runtime-inventory", "wordpress", "sbom", "manual"]}, "path": {"type": "string"}
18
+ }}},
19
+ "components": {"type": "array", "items": {"type": "object", "required": ["ecosystem", "name", "version"], "properties": {
20
+ "purl": {"type": ["string", "null"]}, "ecosystem": {"type": "string"}, "name": {"type": "string"}, "version": {"type": "string"},
21
+ "scope": {"enum": ["runtime", "dev", "build", "os", "service"]}, "direct": {"type": ["boolean", "null"]}, "location": {"type": ["string", "null"]},
22
+ "host": {"type": ["string", "null"], "description": "host alias for OS packages"}
23
+ }}},
24
+ "runtimes": {"type": "array", "items": {"type": "object", "required": ["name", "version"], "properties": {
25
+ "name": {"type": "string"}, "version": {"type": "string"}, "cycle": {"type": ["string", "null"]},
26
+ "host": {"type": ["string", "null"]}, "source": {"type": ["string", "null"]}, "site_root": {"type": ["string", "null"]}
27
+ }}},
28
+ "wordpress": {"type": ["object", "null"], "properties": {
29
+ "core": {"type": ["string", "null"]},
30
+ "plugins": {"type": "array", "items": {"type": "object", "required": ["slug"], "properties": {"slug": {"type": "string"}, "version": {"type": ["string", "null"]}, "active": {"type": ["boolean", "null"]}}}},
31
+ "themes": {"type": "array", "items": {"type": "object", "required": ["slug"], "properties": {"slug": {"type": "string"}, "version": {"type": ["string", "null"]}, "active": {"type": ["boolean", "null"]}}}}
32
+ }},
33
+ "images": {"type": "array", "items": {"type": "object", "required": ["ref"], "properties": {"ref": {"type": "string"}, "digest": {"type": ["string", "null"]}, "host": {"type": ["string", "null"]}}}},
34
+ "hosts": {"type": "array", "items": {"type": "object", "required": ["id"], "properties": {"id": {"type": "string"}, "os": {"type": ["string", "null"]}, "public": {"type": ["boolean", "null"]}}}},
35
+ "watch": {"type": "object", "properties": {"products": {"type": "array", "items": {"type": "string"}}}}
36
+ }
37
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://maggie.noblox.app/contracts/maggie-security/tools-lock-v1.json",
4
+ "title": "Maggie security external tool lock",
5
+ "description": "Pinned external scanners: version, licence class, per-platform asset URL and sha256, required and forbidden flags. See docs/maggie-security/00-foundation-prd.md section 11.",
6
+ "type": "object",
7
+ "required": ["schema", "tools"],
8
+ "properties": {
9
+ "schema": {"const": "maggie-security-tools-lock.v1"},
10
+ "updated": {"type": "string"},
11
+ "tools": {"type": "object", "additionalProperties": {"$ref": "#/$defs/tool"}}
12
+ },
13
+ "$defs": {
14
+ "tool": {
15
+ "type": "object",
16
+ "required": ["version", "licence", "class"],
17
+ "properties": {
18
+ "version": {"type": "string"},
19
+ "licence": {"type": "string"},
20
+ "class": {"enum": ["bundle-ok", "external-only", "reference-only"]},
21
+ "homepage": {"type": "string"},
22
+ "binary": {"type": "string", "description": "Executable name inside the asset (defaults to the tool name)."},
23
+ "version_args": {"type": "array", "items": {"type": "string"}},
24
+ "assets": {"type": "object", "additionalProperties": {"type": "object", "required": ["url", "sha256"], "properties": {
25
+ "url": {"type": "string", "pattern": "^https://"}, "sha256": {"type": "string", "pattern": "^([0-9a-f]{64}|UNPINNED)$"},
26
+ "archive": {"enum": ["none", "tar.gz", "zip"]}, "member": {"type": "string"}
27
+ }}},
28
+ "required_flags": {"type": "array", "items": {"type": "string"}},
29
+ "flags_after_subcommand": {"type": "boolean", "description": "Insert required flags after the first argument (the tool's subcommand)."},
30
+ "forbidden_flags": {"type": "array", "items": {"type": "string"}},
31
+ "env": {"type": "object", "additionalProperties": {"type": "string"}},
32
+ "notes": {"type": "string"}
33
+ }
34
+ }
35
+ }
36
+ }
@@ -4,7 +4,7 @@
4
4
  "skills": [
5
5
  {
6
6
  "name": "maggie-assistant-tools",
7
- "description": "Build an AI assistant's tools once and expose them safely to an in-app agent, an MCP server and ChatGPT/Claude apps. Use for tool registries, risk levels and gates, result cards, approval cards with signed one-time tokens and standing workflow approvals, audit logs, MCP annotations, public discovery MCP and audience binding, visitor-facing receptionists, user-facing capability pages, publishing product CLI/MCP packages and app reviews, and multi-tenant assistant bridge hosts."
7
+ "description": "Build an AI assistant's tools once and expose them safely to an in-app agent, an MCP server and ChatGPT/Claude apps. Use for tool registries, risk levels and gates, result cards, approval cards with signed one-time tokens and standing workflow approvals, audit logs, report inboxes and server-enforced limits for scheduled agents (agent keys, sign-in grants, clipped lists), MCP annotations, public discovery MCP and audience binding, visitor-facing receptionists, user-facing capability pages, publishing product CLI/MCP packages and app reviews, and multi-tenant assistant bridge hosts."
8
8
  },
9
9
  {
10
10
  "name": "maggie-auth-reference",
@@ -74,6 +74,10 @@
74
74
  "name": "maggie-qa-workflow",
75
75
  "description": "Run scenario-based browser QA with explicit evidence, fix/retest lifecycle, and release-gate decisions for web projects."
76
76
  },
77
+ {
78
+ "name": "maggie-security",
79
+ "description": "Check and monitor the security of a Maggie website and the stack it runs on — new CVEs and advisories for its packages (npm, Composer, PyPI, Maven, Go, RubyGems, crates, NuGet), runtimes (Node, PHP, Python, Java, Go, Ruby, .NET), databases (MySQL, MariaDB, PostgreSQL, Redis, MongoDB), web servers, Linux distributions and WordPress core/plugins/themes, end-of-life dates, CISA KEV and EPSS, CVE response plans, and plain-language security reports. Use when the user asks \"is my site secure\", \"are we affected by CVE-…\", \"is this package/plugin safe\", \"is our PHP/MySQL/Ubuntu still supported\", \"security report\", or wants daily security monitoring. Never scans domains the user has not verified; never changes a server."
80
+ },
77
81
  {
78
82
  "name": "maggie-seo-geo",
79
83
  "description": "Plan, audit, create, rewrite, and measure content for AI CMO's paid SEO and GEO workflow. Use for topic opportunities, AI visibility, technical SEO, extractable article structure, sitemap-based rewrites, GSC readback, or SEO/GEO client reports."
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: maggie-assistant-tools
3
- description: Build an AI assistant's tools once and expose them safely to an in-app agent, an MCP server and ChatGPT/Claude apps. Use for tool registries, risk levels and gates, result cards, approval cards with signed one-time tokens and standing workflow approvals, audit logs, MCP annotations, public discovery MCP and audience binding, visitor-facing receptionists, user-facing capability pages, publishing product CLI/MCP packages and app reviews, and multi-tenant assistant bridge hosts.
3
+ description: Build an AI assistant's tools once and expose them safely to an in-app agent, an MCP server and ChatGPT/Claude apps. Use for tool registries, risk levels and gates, result cards, approval cards with signed one-time tokens and standing workflow approvals, audit logs, report inboxes and server-enforced limits for scheduled agents (agent keys, sign-in grants, clipped lists), MCP annotations, public discovery MCP and audience binding, visitor-facing receptionists, user-facing capability pages, publishing product CLI/MCP packages and app reviews, and multi-tenant assistant bridge hosts.
4
4
  metadata:
5
5
  version: 1.0.0
6
6
  ---
@@ -119,6 +119,37 @@ maggie assistant approval-selftest
119
119
  maggie assistant audit-check --registry tools.registry.json --session recorded-session.json
120
120
  ```
121
121
 
122
+ ## Unattended agents: report inbox, server caps, sign-in defaults
123
+
124
+ Scheduled routines (Claude Routines, Codex Automations, cloud tasks) call the
125
+ MCP with nobody watching. Read [unattended agents](references/unattended-agents.md)
126
+ and [report inbox](references/report-inbox.md) before exposing tools to them.
127
+ The registry declares, and `registry-validate` checks:
128
+
129
+ - `reportInbox` — `report_save` (write-reversible, changes nothing else),
130
+ `reports_list`, `report_get`; a per-website daily cap, size limits,
131
+ retention, and agent-written title/summary/body returned as untrusted.
132
+ Every routine ends its run with a report
133
+ ([report schema](../../bundled-contracts/maggie-assistant-tools/report-v1.schema.json);
134
+ check one with `maggie assistant report-check`).
135
+ - `unattended.enforcedBy: "server"` — a prompt is not a limit. Agent keys
136
+ run only the writes their standing permission names, each with `perDay`;
137
+ they cannot confirm previews and a refused write returns the reason.
138
+ Every write a sign-in (OAuth) grant can reach needs `perToolPerDay` or a
139
+ `dailyWriteLimit` the server counts per grant.
140
+ - `unattended.oauth.defaultTools: "role"` — a sign-in connection gets the
141
+ role's full MCP tool set by default; a narrower default needs
142
+ `narrowedReason` (a default copied from one feature, such as translation
143
+ tools only, cuts routines off from the rest of the product).
144
+ - `clips` on a list tool that shortens fields — each shortened item carries
145
+ `clipped`, and `getTool` returns the full text on the same channels. Check a
146
+ recorded result with `maggie assistant list-check`.
147
+
148
+ ```bash
149
+ maggie assistant list-check --registry tools.registry.json --tool social_list --result recorded-list.json
150
+ maggie assistant report-check --report report.json --registry tools.registry.json
151
+ ```
152
+
122
153
  ## Publishing product CLIs and MCP servers
123
154
 
124
155
  See [product release](references/product-release.md):
@@ -140,5 +171,7 @@ See [bridge host](references/bridge-host.md) and
140
171
  - Never let the model see or choose an approval token; never accept a write
141
172
  without one (or a standing approval whose limits cover the call).
142
173
  - Never expose `never` tools or billing changes on MCP or third-party apps.
174
+ - Never rely on a routine's prompt to limit what an unattended caller writes;
175
+ the server counts every cap.
143
176
  - Never publish a package or submit an app for review without an explicit
144
177
  yes; these commands only check.
@@ -0,0 +1,45 @@
1
+ # Report inbox
2
+
3
+ Scheduled agents and the server's own daily jobs need one place to leave
4
+ their results. Without it, a routine's findings exist only in its own run
5
+ transcript and the person never sees them in the product.
6
+
7
+ ## Shape
8
+
9
+ Three tools, declared in `registry.reportInbox`:
10
+
11
+ | Tool (example name) | Risk | Does |
12
+ |---|---|---|
13
+ | `report_save` | write-reversible | saves one report; changes nothing else, so a standing permission may cover it |
14
+ | `reports_list` | read | newest first, title and one-line summary each, unread count; filter by kind / unread |
15
+ | `report_get` | read | one report in full (Markdown body, optional data); marks it read |
16
+
17
+ A report has a `title` (≤ 120 characters), a `summary` of one or two
18
+ sentences (≤ 500) shown in the inbox and the push, a Markdown `body_md`
19
+ (≤ 50,000), optional `data`, a `kind` (`weekly`, `daily_ops`, `agent`,
20
+ `post_health`, …) and a `source` the server sets (`system:<job>` or
21
+ `agent:<key or grant id>`), never the caller.
22
+
23
+ ## Rules
24
+
25
+ - **Capped per website per day** (`perSitePerDay`, for example 20 agent
26
+ reports), counted by the server; body size limited.
27
+ - **Untrusted when read back.** An agent wrote the title, summary and body,
28
+ so `reports_list` and `report_get` return them under the product's
29
+ untrusted marker and readers treat them as data, never instructions
30
+ (`untrusted: ["title", "summary", "body"]`).
31
+ - **Seen where people look.** The newest unread report appears in the app's
32
+ inbox and is pushed (a push type the person can switch off).
33
+ - **Kept for a set time** (`retentionDays`, for example 180).
34
+ - **Every routine ends with `report_save`**, including runs that found
35
+ nothing ("nothing to do today" is a result), and reads `reports_list` first
36
+ so it does not repeat what another run or a server job already reported.
37
+
38
+ ## Before saving
39
+
40
+ ```bash
41
+ maggie assistant report-check --report report.json --registry tools.registry.json
42
+ ```
43
+
44
+ checks the title, summary and body against the registry's limits and refuses
45
+ anything that looks like a secret.
@@ -0,0 +1,70 @@
1
+ # Unattended agents: keys, sign-in grants and clipped lists
2
+
3
+ A scheduled routine (Claude Routines, Codex Automations, a cloud task) calls
4
+ the product's MCP with nobody watching. Three things go wrong when the tool
5
+ surface was designed only for a person in a chat. Each is checked by
6
+ `maggie assistant registry-validate` once the registry declares it.
7
+
8
+ ## 1. A prompt is not a limit
9
+
10
+ A routine's prompt can say "add at most ten ideas a day", but nothing stops
11
+ the next run, a changed prompt, or a confused model from doing more. Every
12
+ write an unattended caller can reach needs a cap the **server** counts.
13
+
14
+ Declare it in `registry.unattended` (`enforcedBy: "server"`):
15
+
16
+ - **Agent keys** (`agentKeys`): an API key made for one routine holds a
17
+ standing permission naming the writes it may run without a preview and a
18
+ daily number for each (`standingTools.<tool>.perDay`). Before such a write
19
+ the server claims one use; when the claim is refused (today's number is
20
+ used, the permission was revoked) the tool returns the reason, not a
21
+ preview (`refusalReturnsReason: true`) — nobody is there to confirm one, and
22
+ an agent key can never confirm previews (`canConfirmPreviews: false`).
23
+ Standing permissions cover reversible or spending writes only; public or
24
+ irreversible writes always go through a person.
25
+ - **Sign-in (OAuth) grants** (`oauth`): a connector the person signed in with
26
+ acts as that person, with their full role. Give the grant its own server
27
+ caps — a total daily write number (`dailyWriteLimit`) and/or one per tool
28
+ (`perToolPerDay`) — that the owner sets on the connections page, and count
29
+ them per grant. The validator fails any write a grant can reach with no cap.
30
+
31
+ Record each claimed use with the key or grant id in the audit log, the same
32
+ way a standing workflow approval is recorded (see
33
+ [approvals and audit](approvals-and-audit.md)).
34
+
35
+ ## 2. The sign-in default is the role's full tool set
36
+
37
+ A grant's default tool set should be what the person's role allows on MCP,
38
+ filtered at call time by the role (`oauth.defaultTools: "role"`). A default
39
+ copied from the first feature that used sign-in (for example only the
40
+ translation tools) leaves a routine connected by sign-in unable to reach the
41
+ rest of the product, with no error that says why. A narrower default is
42
+ allowed only with `narrowedReason`; the validator names the tools it leaves
43
+ out.
44
+
45
+ Re-check membership and role on every call, so removing or demoting a person
46
+ cuts their connected apps off at once.
47
+
48
+ ## 3. Clipped list fields need a full-text get tool
49
+
50
+ List tools keep responses small by shortening long fields (a post's text to
51
+ about 300 characters). An agent asked to check what will be published then
52
+ reports text "cut off mid-sentence" that is in fact whole. For every list
53
+ that shortens fields:
54
+
55
+ - declare `clips` on the list tool: the shortened `fields`, `maxChars`, the
56
+ `getTool` that returns one item in full, and the `idField` it takes;
57
+ - mark each shortened item in the result: `clipped: true` or
58
+ `clipped: ["text"]`;
59
+ - serve the get tool on every channel the list is on, read-only, same scope;
60
+ - say in the list's model-facing description that text is shortened and which
61
+ tool reads it in full.
62
+
63
+ Check a recorded result of the list:
64
+
65
+ ```bash
66
+ maggie assistant list-check --registry tools.registry.json --tool social_list --result recorded-list.json
67
+ ```
68
+
69
+ It fails items whose field reaches `maxChars` (or ends with an ellipsis)
70
+ without a `clipped` marker, and items without the id the get tool needs.
@@ -60,10 +60,17 @@ API Pull deliveries need their live URL recorded so social posts and internal
60
60
  links point at the page that exists now: the site reports it on publish
61
61
  (`maggie blog live-urls record --content-id ID --url URL`), and
62
62
  `maggie blog live-urls match --sitemap URL --write` fills the gaps
63
- additively — it never retires an earlier match, and the original page wins
64
- over translated copies that share the slug. See
63
+ additively — it never retires an earlier match, a post tracked with an empty
64
+ URL is still matched, and the original page wins over translated copies that
65
+ share the slug. See
65
66
  [where a delivered post went live](../../bundled-tools/integrations/maggie-api-pull.md#where-a-delivered-post-went-live).
66
67
 
68
+ A pull site also pulls rewrites (`GET /updates`, same schedule as `/posts`):
69
+ apply each one to the post it is for (`source_content_id`, else slug or
70
+ address, previous slugs too), change only the body, keep the replaced body for
71
+ undo, hold `publication_status: draft` rewrites and never create a post from
72
+ one. See [rewrites on pull sites](../../bundled-tools/integrations/maggie-api-pull.md#rewrites-on-pull-sites).
73
+
67
74
  Automatic publication is an opt-in host policy, not the default. Keep human
68
75
  review enabled unless the owner explicitly chooses otherwise. If a host has
69
76
  that approval, validate its evidence before its scheduler calls the host's
@@ -163,7 +163,7 @@ Use `--schedule systemd` or `--schedule cron` with `--ready` only to generate a
163
163
  reviewable scheduler artifact; enabling it remains an operator action after
164
164
  backup, migration, and release evidence checks.
165
165
 
166
- The default installer source is MaggieDash `main` (currently `0.2.14`; pin
166
+ The default installer source is MaggieDash `main` (currently `0.2.15`; pin
167
167
  another release with `--ref`). It contains the released Astro `hostBootstrap`
168
168
  manifest and 47-route Booking source, including the tenant-scoped treatment
169
169
  package catalogue, and follows the booking rules above (manage-link state