@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.
- package/README-zh-TW.md +25 -23
- package/README.md +93 -71
- package/bin/maggie.js +14 -2
- package/bundled-contracts/maggie-assistant-tools/booking-receptionist-example-v1.json +18 -2
- package/bundled-contracts/maggie-assistant-tools/report-v1.schema.json +43 -0
- package/bundled-contracts/maggie-assistant-tools/tool-registry-example-v1.json +249 -11
- package/bundled-contracts/maggie-assistant-tools/tool-registry-v1.schema.json +175 -0
- package/bundled-contracts/maggie-deployment/readiness-v1.schema.json +2 -1
- package/bundled-contracts/maggie-ops/agent-routines-v1.schema.json +48 -0
- package/bundled-contracts/maggie-security/finding-example-v1.json +89 -0
- package/bundled-contracts/maggie-security/finding-v1.schema.json +63 -0
- package/bundled-contracts/maggie-security/findings-set-example-v1.json +148 -0
- package/bundled-contracts/maggie-security/findings-set-v1.schema.json +32 -0
- package/bundled-contracts/maggie-security/protect-plan-v1.schema.json +28 -0
- package/bundled-contracts/maggie-security/report-v1.schema.json +29 -0
- package/bundled-contracts/maggie-security/stack-example-v1.json +66 -0
- package/bundled-contracts/maggie-security/stack-upload-v1.schema.json +22 -0
- package/bundled-contracts/maggie-security/stack-v1.schema.json +37 -0
- package/bundled-contracts/maggie-security/tools-lock-v1.schema.json +36 -0
- package/bundled-skills/catalog.json +5 -1
- package/bundled-skills/maggie-assistant-tools/SKILL.md +34 -1
- package/bundled-skills/maggie-assistant-tools/references/report-inbox.md +45 -0
- package/bundled-skills/maggie-assistant-tools/references/unattended-agents.md +70 -0
- package/bundled-skills/maggie-blog/SKILL.md +9 -2
- package/bundled-skills/maggie-booking/SKILL.md +1 -1
- package/bundled-skills/maggie-dash/SKILL.md +9 -0
- package/bundled-skills/maggie-deployment/SKILL.md +77 -1
- package/bundled-skills/maggie-deployment/references/vps.md +5 -0
- package/bundled-skills/maggie-marketplace/SKILL.md +21 -1
- package/bundled-skills/maggie-ops/SKILL.md +28 -0
- package/bundled-skills/maggie-ops/references/agents-repository.md +108 -0
- package/bundled-skills/maggie-ops/references/ops-autopilot.md +65 -0
- package/bundled-skills/maggie-ops/references/routine-mode.md +92 -0
- package/bundled-skills/maggie-security/SKILL.md +172 -0
- package/bundled-skills/maggie-security/agents/openai.yaml +4 -0
- package/bundled-skills/maggie-security/data/LICENSE-NOTICE.md +24 -0
- package/bundled-skills/maggie-security/data/asvs-map.json +209 -0
- package/bundled-skills/maggie-security/data/fail2ban/filter.d/maggie-wordpress.conf +6 -0
- package/bundled-skills/maggie-security/data/semgrep/LICENSE-NOTICE.md +5 -0
- package/bundled-skills/maggie-security/data/semgrep/VERSION +1 -0
- package/bundled-skills/maggie-security/data/semgrep/rules/dockerfile.yaml +14 -0
- package/bundled-skills/maggie-security/data/semgrep/rules/generic.yaml +26 -0
- package/bundled-skills/maggie-security/data/semgrep/rules/js.yaml +216 -0
- package/bundled-skills/maggie-security/data/semgrep/rules/php-debug-ok.yaml +17 -0
- package/bundled-skills/maggie-security/data/semgrep/rules/php-debug.yaml +17 -0
- package/bundled-skills/maggie-security/data/semgrep/rules/php.yaml +101 -0
- package/bundled-skills/maggie-security/data/semgrep/tests/dockerfile.dockerfile +10 -0
- package/bundled-skills/maggie-security/data/semgrep/tests/generic.astro +11 -0
- package/bundled-skills/maggie-security/data/semgrep/tests/generic.conf +11 -0
- package/bundled-skills/maggie-security/data/semgrep/tests/js.jsx +95 -0
- package/bundled-skills/maggie-security/data/semgrep/tests/php-debug-ok.php +5 -0
- package/bundled-skills/maggie-security/data/semgrep/tests/php-debug.php +3 -0
- package/bundled-skills/maggie-security/data/semgrep/tests/php.php +55 -0
- package/bundled-skills/maggie-security/evals/evals.json +97 -0
- package/bundled-skills/maggie-security/references/commands.md +111 -0
- package/bundled-skills/maggie-security/references/cve-response.md +24 -0
- package/bundled-skills/maggie-security/references/explaining-findings.md +57 -0
- package/bundled-skills/maggie-security/references/findings.md +39 -0
- package/bundled-skills/maggie-security/references/ownership-and-consent.md +29 -0
- package/bundled-skills/maggie-security/references/site-types.md +22 -0
- package/bundled-skills/maggie-security/references/tools-and-licences.md +16 -0
- package/bundled-skills/maggie-security/references/workflows.md +23 -0
- package/bundled-skills/maggie-security/registry/security-tools.registry.json +628 -0
- package/bundled-skills/maggie-security/routines.example.json +27 -0
- package/bundled-skills/maggie-seo-geo/SKILL.md +9 -1
- package/bundled-skills/maggie-social-share/SKILL.md +20 -0
- package/bundled-tools/clis/maggie.py +63 -3
- package/bundled-tools/clis/maggie_assistant_tools.py +225 -1
- package/bundled-tools/clis/maggie_deployment_readiness.py +17 -2
- package/bundled-tools/clis/maggie_host_runtime.py +458 -0
- package/bundled-tools/clis/maggie_live_urls.py +11 -2
- package/bundled-tools/clis/maggie_ops.py +2 -0
- package/bundled-tools/clis/maggie_ops_routines.py +352 -0
- package/bundled-tools/clis/maggie_query_ideas.py +154 -0
- package/bundled-tools/clis/maggie_security.py +342 -0
- package/bundled-tools/clis/maggie_security_agent.py +326 -0
- package/bundled-tools/clis/maggie_security_code.py +650 -0
- package/bundled-tools/clis/maggie_security_core.py +1512 -0
- package/bundled-tools/clis/maggie_security_deps.py +560 -0
- package/bundled-tools/clis/maggie_security_health.py +415 -0
- package/bundled-tools/clis/maggie_security_host.py +511 -0
- package/bundled-tools/clis/maggie_security_hosted.py +115 -0
- package/bundled-tools/clis/maggie_security_intel.py +1294 -0
- package/bundled-tools/clis/maggie_security_inventory.py +1023 -0
- package/bundled-tools/clis/maggie_security_logs.py +777 -0
- package/bundled-tools/clis/maggie_security_mcp.py +473 -0
- package/bundled-tools/clis/maggie_security_mirror.py +122 -0
- package/bundled-tools/clis/maggie_security_protect.py +519 -0
- package/bundled-tools/clis/maggie_security_report.py +506 -0
- package/bundled-tools/clis/maggie_security_standards.py +214 -0
- package/bundled-tools/clis/maggie_security_versions.py +381 -0
- package/bundled-tools/clis/maggie_security_web.py +936 -0
- package/bundled-tools/clis/maggie_skill_catalog.py +16 -2
- package/bundled-tools/clis/maggie_social_share.py +101 -1
- package/bundled-tools/clis/maggie_version_sources.py +93 -0
- package/bundled-tools/clis/security_data/eol-snapshot.json +1 -0
- package/bundled-tools/clis/security_data/gitleaks-rules.json +3812 -0
- package/bundled-tools/clis/security_data/maltrail-lists.json +1 -0
- package/bundled-tools/clis/security_data/public-suffix-icann.txt +7374 -0
- package/bundled-tools/clis/security_data/retire-extractors.json +695 -0
- package/bundled-tools/clis/security_data/sigma-web.json +6514 -0
- package/bundled-tools/clis/security_data/tools.lock.json +358 -0
- package/bundled-tools/integrations/maggie-api-pull.md +28 -1
- 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,
|
|
64
|
-
|
|
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.
|
|
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
|