@passioncode-ai/passioncode 0.1.34 → 0.1.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.35 - 2026-10-12
4
+
5
+ ### Changed
6
+
7
+ - **Fabric Agent Adapter is pinned at `v0.11.1`** (it was `v0.10.0`). A service built with the kit can now check a
8
+ delegation token and an operator's approval offline, in Python and Node, with the same answers as the Fabric Agent
9
+ Contract's own verifier (DEC-0039). It can put a gate in front of its MCP tools, so each call names the person it
10
+ is for, the calling agent and the chain, and an approval is used once. The Node kit refuses small-order Ed25519
11
+ keys itself (Node 20 and 22 accepted a forged signature under one). The contract pin is unchanged at `8e49fbd`.
12
+
3
13
  ## 0.1.34 - 2026-10-11
4
14
 
5
15
  ### Changed
package/family.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "name": "fabric-agent-adapter",
9
9
  "displayName": "Fabric Agent Adapter",
10
10
  "repo": "passioncode-ai/fabric-agent-adapter",
11
- "ref": "v0.10.0",
11
+ "ref": "v0.11.1",
12
12
  "kind": "plugin",
13
13
  "path": "plugins/fabric-agent-adapter",
14
14
  "legacyPluginIds": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@passioncode-ai/passioncode",
3
- "version": "0.1.34",
3
+ "version": "0.1.35",
4
4
  "description": "The PassionCode.ai agent skill set \u2014 Fabric Agent Adapter, Observatory Log and the organisation's working rules \u2014 for Claude Code and every other agent on the machine, updated as one set.",
5
5
  "bin": {
6
6
  "passioncode": "bin/passioncode.js"
@@ -11,7 +11,7 @@
11
11
  "name": "fabric-agent-adapter",
12
12
  "displayName": "Fabric Agent Adapter",
13
13
  "source": "./plugins/fabric-agent-adapter",
14
- "version": "0.10.0",
14
+ "version": "0.11.1",
15
15
  "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.",
16
16
  "author": {
17
17
  "name": "PassionCode.ai",
@@ -35,7 +35,7 @@
35
35
  "name": "passioncode",
36
36
  "displayName": "PassionCode.ai",
37
37
  "source": "./plugins/passioncode",
38
- "version": "0.1.34",
38
+ "version": "0.1.35",
39
39
  "description": "The organisation's working rules for every contributor's agent (working-in-passioncode), and a once-a-day check that keeps the PassionCode.ai set current.",
40
40
  "author": {
41
41
  "name": "PassionCode.ai",
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "family": "passioncode",
3
- "version": "0.1.34",
3
+ "version": "0.1.35",
4
4
  "release": true,
5
5
  "members": [
6
6
  {
7
7
  "name": "fabric-agent-adapter",
8
8
  "displayName": "Fabric Agent Adapter",
9
9
  "repo": "passioncode-ai/fabric-agent-adapter",
10
- "ref": "v0.10.0",
11
- "commit": "2226d197a5d60cafc6dfb71b1ff91c4fcec4909e",
12
- "version": "0.10.0",
10
+ "ref": "v0.11.1",
11
+ "commit": "ea7efbea9a6eba6615881103035cf1a0bdec8db8",
12
+ "version": "0.11.1",
13
13
  "via": "clone of https://***@github.com/passioncode-ai/fabric-agent-adapter.git",
14
14
  "skills": [
15
15
  "adapting-projects-to-fabric",
@@ -22,7 +22,7 @@
22
22
  "legacyMarketplaces": [
23
23
  "fabric-agent-adapter"
24
24
  ],
25
- "contentHash": "sha256:69faa1f800cfd79d53e1fab195a981de64e1b72fac9d52f522e593646350a999",
25
+ "contentHash": "sha256:71ec7cc98186f74e36dc82839fe8dea7b95454bca70f41e8f66cd7f8aaa9aaf7",
26
26
  "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.",
27
27
  "author": {
28
28
  "name": "PassionCode.ai",
@@ -61,16 +61,16 @@
61
61
  "name": "passioncode",
62
62
  "displayName": "PassionCode.ai",
63
63
  "repo": "passioncode-ai/passioncode",
64
- "ref": "v0.1.34",
64
+ "ref": "v0.1.35",
65
65
  "commit": null,
66
- "version": "0.1.34",
66
+ "version": "0.1.35",
67
67
  "via": "this repository",
68
68
  "skills": [
69
69
  "working-in-passioncode"
70
70
  ],
71
71
  "legacyPluginIds": [],
72
72
  "legacyMarketplaces": [],
73
- "contentHash": "sha256:8af19415de312c6bc641c003d691351e43bab07cb7fbef81c53e8fd3b5e24d25",
73
+ "contentHash": "sha256:afeca4f36bf8ce531b78d77f071a7e3ade1944eba31869916d711c9a191d1580",
74
74
  "description": "The organisation's working rules for every contributor's agent (working-in-passioncode), and a once-a-day check that keeps the PassionCode.ai set current.",
75
75
  "author": {
76
76
  "name": "PassionCode.ai",
@@ -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.10.0",
6
+ "version": "0.11.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.10.0"
8
+ version: "0.11.1"
9
9
  contract-version: "0.1.0"
10
10
  contract-commit: "8e49fbd5fbbf230e32c1969cd24ac3c22422f0a5"
11
11
  ---
@@ -16,7 +16,7 @@ license: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
16
16
  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.
17
17
  metadata:
18
18
  author: PassionCode.ai
19
- version: "0.10.0"
19
+ version: "0.11.1"
20
20
  contract-version: "0.1.0"
21
21
  extension: "fabric-service/0.1"
22
22
  extension-commit: "8e49fbd5fbbf230e32c1969cd24ac3c22422f0a5"
@@ -80,7 +80,10 @@ each manifest capability is the tool of its name, long work is a job with a stab
80
80
  a question for a person is an elicitation, and every call carries one trace. Read
81
81
  [the interop reference](references/interop.md) before writing an MCP tool; the helpers
82
82
  are in [`scripts/fabric_interop.py`](scripts/fabric_interop.py) and
83
- [`scripts/fabric-interop.mjs`](scripts/fabric-interop.mjs).
83
+ [`scripts/fabric-interop.mjs`](scripts/fabric-interop.mjs). When the callers are agents of the estate, the
84
+ service checks each call's delegation token (DEC-0039): read [the delegation reference](references/delegation.md);
85
+ the verifier is [`scripts/fabric_delegation.py`](scripts/fabric_delegation.py) /
86
+ [`scripts/fabric-delegation.mjs`](scripts/fabric-delegation.mjs).
84
87
 
85
88
  ## Step 2 — the non-negotiables
86
89
 
@@ -0,0 +1,84 @@
1
+ # Delegation — checking who acts for whom (DEC-0039)
2
+
3
+ A service that other agents of the estate call checks each call offline with the kit's verifier: the estate hub
4
+ signs a delegation token naming the person (`sub`), the actor chain (`act`), this service (`aud`), the
5
+ capabilities (`scope`) and the effect ceiling (`effect`); the service checks the signature against the estate's
6
+ published keys and answers `ok` or one refusal code. Contract: `docs/specification/delegation.md` (DL-1…DL-19)
7
+ at the pin. Python: [`scripts/fabric_delegation.py`](../scripts/fabric_delegation.py); Node:
8
+ [`scripts/fabric-delegation.mjs`](../scripts/fabric-delegation.mjs). Both answer the shared vectors exactly as the
9
+ contract's own verifier does.
10
+
11
+ ## Contents
12
+
13
+ - Declaring it
14
+ - Wiring the gate
15
+ - Approvals
16
+ - What a refusal looks like
17
+ - Keys and the cache
18
+ - What the kit does not do
19
+
20
+ ## Declaring it
21
+
22
+ In the well-known document: `surfaces.mcp.auth: "delegation"` (only delegation tokens) and
23
+ `auth.delegation: {issuer, jwks}` — the `iss` you trust (`urn:fabric:estate:<id>`) and where the key set is read.
24
+ The descriptor's token stays the host's: it is never a caller's credential on `/mcp` (DL-12). The probe checks
25
+ the declaration (`auth.delegation-declared`) and that `/mcp` refuses the descriptor token.
26
+
27
+ ## Wiring the gate
28
+
29
+ ```python
30
+ import fabric_delegation as fd, fabric_interop as fi
31
+ keys = fd.JwksCache(well_known["auth"]["delegation"]["jwks"]) # https, loopback http, or a file
32
+ gate = fd.delegation_gate(audience="example-agent", jwks=keys, issuer=well_known["auth"]["delegation"]["issuer"],
33
+ effects={"example.write": "draft", "example.publish": "publish"}) # each tool's manifest effect
34
+ server = fi.McpToolServer("example-agent", VERSION, authorize=gate) # pass the request headers to handle()
35
+ # in a handler: ctx.delegation["principal"], ["caller"], ["chain"] — record the chain with the work
36
+ ```
37
+
38
+ ```js
39
+ import { JwksCache, delegationGate, refusalToolResult } from './fabric-delegation.mjs';
40
+ const gate = delegationGate({ audience: 'example-agent', jwks: new JwksCache(wk.auth.delegation.jwks), issuer: wk.auth.delegation.issuer,
41
+ effects: { 'example.write': 'draft' } });
42
+ const verdict = await gate(params.name, req.headers);
43
+ if (!verdict.ok) return refusalToolResult(verdict);
44
+ ```
45
+
46
+ The token is read from `Fabric-Delegation` first (a forwarded call; present but empty is refused, never skipped),
47
+ then from `Authorization: Bearer` when the bearer is a delegation JWT (DL-9, DL-10). A tool with no declared
48
+ effect is refused (`unknown-state`), never guessed. The checks run in the DL-13 order; nothing about a token is
49
+ believed before its signature. The built-in job tools (`fabric.job.get`, `fabric.job.cancel`) are gated too: by the
50
+ job's own capability and effect, and only for the principal and caller that started the job (another caller is
51
+ `scope-not-granted`); `on_input` gets the checked delegation on its context. Start jobs with `ctx.start_job()` so the
52
+ job records who started it.
53
+
54
+ ## Approvals
55
+
56
+ An action with an external effect may need the operator's approval (DL-17, DL-18). The order is fixed: the token,
57
+ then the grant check where there is one, then `verify_approval` / `verifyApproval`, which consumes the approval's
58
+ `jti` last, then the action. Without an approval, answer `approval-required` with
59
+ `action_digest(action)` / `actionDigest(action)` — the SHA-256 of the action's RFC 8785 form (`jcs`) — so the caller
60
+ can ask the hub. Keep consumed ids in `FileJtiStore` (0600, survives a restart); `MemoryJtiStore` is for tests
61
+ and `UNSAFE_NO_JTI_STORE` exists only by name. No store at all, or a store file that cannot be read, is
62
+ `unknown-state` — never a pass.
63
+
64
+ ## What a refusal looks like
65
+
66
+ DL-19: an MCP tool answers `refusal_tool_result(r)` / `refusalToolResult(r)` — `isError: true` and
67
+ `structuredContent: {error: {code, message, data: {detail}}}`; an HTTP route answers `refusal_http(r)` /
68
+ `refusalHttp(r)` with the code's status (401 for `unauthenticated`, `token-expired`, `principal-unproven`, with
69
+ `WWW-Authenticate: Bearer error="invalid_token"`; 503 for `issuer-unavailable` and `unknown-state`; 403 for the
70
+ rest). `detail` is a short machine word; the token, the approval and the keys never appear in a result or a log.
71
+
72
+ ## Keys and the cache
73
+
74
+ `JwksCache` holds the estate's key set at most 10 minutes and, on a `kid` it does not hold, re-reads at most once
75
+ a minute (DL-15), and waits 10 s after a failed read before trying again; after 10 minutes without a successful read it answers nothing, and the verifier says
76
+ `issuer-unavailable`. It reads https, http on loopback only, or a file; a URL with credentials is refused. The
77
+ Python kit verifies Ed25519 itself (RFC 8032, standard library only, strict as OpenSSL: `S` below the group order,
78
+ canonical points, no small-order key); it follows no redirect when it reads the key set; the Node kit uses `node:crypto` and refuses small-order keys
79
+ itself (`isSmallOrderKey`), because Node before 26 lets OpenSSL accept a signature under one.
80
+
81
+ ## What the kit does not do
82
+
83
+ It does not mint tokens, check attenuation against a parent (the issuer's rule, DL-5), check a grant or a spend
84
+ window (the meter's, DL-21), or decide which actions need an approval — the service decides that.
@@ -72,7 +72,7 @@ No auth; the Host/Origin guard applies; answered from memory in under 100 ms.
72
72
  the MCP surface takes only the estate's delegation tokens, and the top-level
73
73
  `auth.delegation {issuer, jwks}` is then required. With `own` or `delegation` the descriptor's
74
74
  token is not an MCP credential: a host and the probe never call `/mcp` with it as a caller.
75
- The kits do not verify delegation tokens yet (a later FAA-20 release).
75
+ The kits verify them with `fabric_delegation` / `fabric-delegation.mjs` ([delegation](delegation.md)).
76
76
 
77
77
  ## Events page — `GET /fabric/v1/events?after=<cursor>&limit=<n>`
78
78
 
@@ -15,8 +15,8 @@
15
15
  - **Delegation (DEC-0039, DL-16).** `surfaces.mcp.auth: "delegation"` means `/mcp` takes only
16
16
  the estate's delegation tokens; declare `auth.delegation {issuer, jwks}` in the well-known
17
17
  document. The probe treats it like `own` and checks the declaration
18
- (`auth.delegation-declared`). The kits do not verify the tokens yet; until they do, name what
19
- checks them.
18
+ (`auth.delegation-declared`). The kits verify the tokens: put `delegation_gate` /
19
+ `delegationGate` in front of the tools — see [the delegation reference](delegation.md).
20
20
  - Register it into a client config with the service's own command
21
21
  (`<tool> mcp-register`), which writes `{"type":"http","url":"http://127.0.0.1:<port>/mcp","headers":{...}}`
22
22
  atomically, aborts if the file changed meanwhile, and keeps one 0600 backup. The token