@passioncode-ai/fabric-agent-adapter 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/package.json +1 -1
- package/plugins/fabric-agent-adapter/.claude-plugin/plugin.json +1 -1
- package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/SKILL.md +1 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/SKILL.md +1 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/remote-placement.md +8 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service.py +20 -2
- package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/SKILL.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.1 - 2026-10-03
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **`check_service.py` no longer fails every online service hosted behind a platform router.**
|
|
8
|
+
`network.host-check` required the service's own `403`, but Heroku, Fly, Render and CDNs route
|
|
9
|
+
by `Host`: a foreign one is answered by the router (`404`/`421`) and never reaches the process.
|
|
10
|
+
For a remote placement that answer now passes, unless its body is the well-known document. The
|
|
11
|
+
Origin and cross-site checks are unchanged — they reach the service and need its `403`. Found on
|
|
12
|
+
the first real online service: 26 PASS and 1 false FAIL before, 0 FAIL after (`guard_verdict`,
|
|
13
|
+
`test/test_fabric_service_remote.py::GuardVerdict`, 4 mutations killed).
|
|
14
|
+
|
|
3
15
|
## 0.6.0 - 2026-10-02
|
|
4
16
|
|
|
5
17
|
### Added
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@passioncode-ai/fabric-agent-adapter",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Create Fabric-compatible agents, run them as always-alive local services with dashboards (fabric-service/0.1), and adapt existing projects to the Fabric Agent Contract. This package is the installer CLI.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "python3 test/validate.py && python3 -m unittest discover -s test -q && node --test 'test/*.test.mjs'"
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "fabric-agent-adapter",
|
|
4
4
|
"displayName": "Fabric Agent Adapter",
|
|
5
5
|
"description": "Create new Fabric-compatible agents, build them as always-alive local services with dashboards (fabric-service/0.1), and adapt existing projects to the Fabric Agent Contract through evidence-backed MCP, A2A, or local-runner provider bundles.",
|
|
6
|
-
"version": "0.6.
|
|
6
|
+
"version": "0.6.1",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "PassionCode.ai",
|
|
9
9
|
"url": "https://passioncode.ai/"
|
|
@@ -5,7 +5,7 @@ license: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
|
5
5
|
compatibility: Requires filesystem access and Python 3.9+. Exact schema checks additionally need git, Node.js, pnpm, and the pinned fabric-agent-contract checkout (a public repository). Works without those tools in an explicitly degraded structural-check mode.
|
|
6
6
|
metadata:
|
|
7
7
|
author: PassionCode.ai
|
|
8
|
-
version: "0.6.
|
|
8
|
+
version: "0.6.1"
|
|
9
9
|
contract-version: "0.1.0"
|
|
10
10
|
contract-commit: "2ce392291c6668598d12cd38327e24696b5ca15c"
|
|
11
11
|
---
|
|
@@ -15,7 +15,7 @@ license: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
|
15
15
|
compatibility: Python 3.9+ or Node.js 20+ for the kits; the probe needs Python 3.9+. launchd steps are macOS-only (Linux services use lifecycle manager none until a systemd adapter exists). Dashboard handoff optionally uses Fabric Dashboards MCP link/host_status/open; without it, report unresolved host capability. The contract checkout is optional.
|
|
16
16
|
metadata:
|
|
17
17
|
author: PassionCode.ai
|
|
18
|
-
version: "0.6.
|
|
18
|
+
version: "0.6.1"
|
|
19
19
|
contract-version: "0.1.0"
|
|
20
20
|
extension: "fabric-service/0.1"
|
|
21
21
|
extension-commit: "2ce392291c6668598d12cd38327e24696b5ca15c"
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/remote-placement.md
CHANGED
|
@@ -44,6 +44,14 @@ same objects — well-known document, events feed, login code — at the same pa
|
|
|
44
44
|
- **Behind a router**: check the platform-set forwarded scheme; `Host` is preserved by common
|
|
45
45
|
platforms and must equal the origin's host.
|
|
46
46
|
|
|
47
|
+
## Checking it
|
|
48
|
+
|
|
49
|
+
`check_service.py <id>` probes a remote placement over verified TLS. Behind a platform router
|
|
50
|
+
(Heroku, Fly, Render, a CDN) a request that names a foreign `Host` never reaches the process: the
|
|
51
|
+
router answers it, usually `404` or `421`. The probe counts that as the refusal it is, as long as
|
|
52
|
+
the body is not the well-known document. The Origin and cross-site checks name the right `Host`,
|
|
53
|
+
reach the service, and still need its own `403`.
|
|
54
|
+
|
|
47
55
|
## What a host does and will not do
|
|
48
56
|
|
|
49
57
|
| Situation | Host |
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service.py
CHANGED
|
@@ -79,6 +79,23 @@ def priority_problems(plist: dict) -> list:
|
|
|
79
79
|
return out
|
|
80
80
|
|
|
81
81
|
|
|
82
|
+
# A platform router (Heroku, Fly, Render, a CDN) routes by Host, so a request naming a foreign
|
|
83
|
+
# Host never reaches an online service: the router itself answers, typically 404 or 421. That is
|
|
84
|
+
# still a refusal — the service disclosed nothing — so for a remote placement the host check
|
|
85
|
+
# accepts it, as long as the body is not the well-known document. Every other guard request names
|
|
86
|
+
# the right Host, reaches the service, and must be the service's own 403.
|
|
87
|
+
PLATFORM_HOST_REFUSALS = (400, 404, 421)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def guard_verdict(rule: str, remote: bool, status: int, body: bytes) -> Tuple[str, str]:
|
|
91
|
+
if status == 403:
|
|
92
|
+
return "PASS", "HTTP 403"
|
|
93
|
+
disclosed = b"fabric-service/" in (body or b"")
|
|
94
|
+
if rule == "network.host-check" and remote and status in PLATFORM_HOST_REFUSALS and not disclosed:
|
|
95
|
+
return "PASS", "HTTP %d from the platform router: a foreign Host never reaches the service" % status
|
|
96
|
+
return "FAIL", "HTTP %d%s" % (status, ", and the body is the well-known document" if disclosed else "")
|
|
97
|
+
|
|
98
|
+
|
|
82
99
|
class _PinnedHTTPS(http.client.HTTPSConnection):
|
|
83
100
|
"""HTTPS to the origin's name (SNI, certificate, Host) over a socket dialled elsewhere."""
|
|
84
101
|
|
|
@@ -243,8 +260,9 @@ class Probe:
|
|
|
243
260
|
sent.update(self.auth_headers())
|
|
244
261
|
if "Origin" in sent:
|
|
245
262
|
sent["Origin"] = "https://evil.example"
|
|
246
|
-
status, _,
|
|
247
|
-
|
|
263
|
+
status, _, body = self.request("GET", "/.well-known/fabric-service", sent)
|
|
264
|
+
verdict, evidence = guard_verdict(rule, self.remote, status, body)
|
|
265
|
+
self.add(rule, verdict, evidence)
|
|
248
266
|
except (OSError, ssl.SSLError) as exc:
|
|
249
267
|
self.add(rule, "NOT_RUN", str(exc))
|
|
250
268
|
if self.remote:
|
|
@@ -5,7 +5,7 @@ license: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
|
5
5
|
compatibility: Requires filesystem access and Python 3.9+. Exact schema checks additionally need git, Node.js, pnpm, and the pinned fabric-agent-contract checkout (a public repository). Works without those tools in an explicitly degraded structural-check mode. Ships in one plugin with adapting-projects-to-fabric, whose scripts it reuses.
|
|
6
6
|
metadata:
|
|
7
7
|
author: PassionCode.ai
|
|
8
|
-
version: "0.6.
|
|
8
|
+
version: "0.6.1"
|
|
9
9
|
contract-version: "0.1.0"
|
|
10
10
|
contract-commit: "2ce392291c6668598d12cd38327e24696b5ca15c"
|
|
11
11
|
---
|