@passioncode-ai/passioncode 0.2.24 → 0.2.26
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 +17 -0
- package/family.json +1 -1
- package/package.json +1 -1
- package/payload/.claude-plugin/marketplace.json +2 -2
- package/payload/manifest.json +8 -8
- package/payload/plugins/fabric-agent-adapter/.claude-plugin/plugin.json +1 -1
- package/payload/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/SKILL.md +3 -3
- package/payload/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/adapt_project.py +2 -2
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/SKILL.md +2 -2
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/references/board.md +3 -1
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/references/delegation.md +1 -1
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/references/kit-modules.md +3 -3
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/references/protocol.md +2 -2
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-base.mjs +1 -1
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-session.mjs +5 -2
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-shapes.mjs +18 -2
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-delegation.mjs +5 -7
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-descriptor.mjs +1 -1
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-paths.mjs +13 -11
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-platform.mjs +1 -1
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-protocols.mjs +2 -1
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_base.py +1 -1
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board_session.py +6 -3
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board_shapes.py +25 -2
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_delegation.py +5 -11
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_descriptor.py +2 -2
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_paths.py +8 -8
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_platform.py +1 -1
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_protocols.py +2 -2
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/kit.json +220 -66
- package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/share-registration.schema.json +3 -2
- package/payload/plugins/fabric-agent-adapter/skills/creating-fabric-agents/SKILL.md +3 -3
- package/payload/plugins/fabric-agent-adapter/skills/working-with-fabric/SKILL.md +1 -1
- package/payload/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_env.py +1 -1
- package/payload/plugins/passioncode/.claude-plugin/plugin.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.26 - 2026-10-23
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **Fabric Agent Adapter is pinned at `v0.45.0`** (it was `v0.44.2`): pinned to the Fabric Agent Contract's
|
|
8
|
+
`e742016`; the board kit reads the board as Fabric 0.3.9 serves it (the `answered` state, the read counts, a request
|
|
9
|
+
nobody can answer now), a peer may be `processor-hosted`, and three new protocols are known. Notes are in the
|
|
10
|
+
adapter's CHANGELOG.
|
|
11
|
+
|
|
12
|
+
## 0.2.25 - 2026-10-22
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- **Fabric Agent Adapter is pinned at `v0.44.2`** (it was `v0.44.1`): the kit writes its consumed-approval file
|
|
17
|
+
owner-only on every platform (a protected ACL on Windows), and its private writer leaves no temporary file behind
|
|
18
|
+
whatever fails. Notes are in the adapter's CHANGELOG.
|
|
19
|
+
|
|
3
20
|
## 0.2.24 - 2026-10-22
|
|
4
21
|
|
|
5
22
|
### Changed
|
package/family.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@passioncode-ai/passioncode",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.26",
|
|
4
4
|
"description": "Set up PassionCode.ai on a computer with one command — the apps from their verified releases, their MCP servers for every coding agent and the PassionCode.ai skills — and check and repair it with the same command or `doctor`.",
|
|
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.
|
|
14
|
+
"version": "0.45.0",
|
|
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; and teach a coding agent to work in a project through Fabric (fabric-mcp, fabric_whoami, claim and release), with Claude Code session hooks.",
|
|
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.2.
|
|
38
|
+
"version": "0.2.26",
|
|
39
39
|
"description": "Set up and check PassionCode.ai on a computer with one command (setting-up-passioncode), 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",
|
package/payload/manifest.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"family": "passioncode",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.26",
|
|
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.
|
|
11
|
-
"commit": "
|
|
12
|
-
"version": "0.
|
|
10
|
+
"ref": "v0.45.0",
|
|
11
|
+
"commit": "29ed8883b266b9265540cbce142309830cde01d1",
|
|
12
|
+
"version": "0.45.0",
|
|
13
13
|
"via": "clone of https://***@github.com/passioncode-ai/fabric-agent-adapter.git",
|
|
14
14
|
"skills": [
|
|
15
15
|
"adapting-projects-to-fabric",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"legacyMarketplaces": [
|
|
24
24
|
"fabric-agent-adapter"
|
|
25
25
|
],
|
|
26
|
-
"contentHash": "sha256:
|
|
26
|
+
"contentHash": "sha256:160e78c3b3e803119935319e98e6312cf1f503bd966562bcfa8b0cb332daf1a7",
|
|
27
27
|
"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; and teach a coding agent to work in a project through Fabric (fabric-mcp, fabric_whoami, claim and release), with Claude Code session hooks.",
|
|
28
28
|
"author": {
|
|
29
29
|
"name": "PassionCode.ai",
|
|
@@ -62,9 +62,9 @@
|
|
|
62
62
|
"name": "passioncode",
|
|
63
63
|
"displayName": "PassionCode.ai",
|
|
64
64
|
"repo": "passioncode-ai/passioncode",
|
|
65
|
-
"ref": "v0.2.
|
|
65
|
+
"ref": "v0.2.26",
|
|
66
66
|
"commit": null,
|
|
67
|
-
"version": "0.2.
|
|
67
|
+
"version": "0.2.26",
|
|
68
68
|
"via": "this repository",
|
|
69
69
|
"skills": [
|
|
70
70
|
"setting-up-passioncode",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
],
|
|
73
73
|
"legacyPluginIds": [],
|
|
74
74
|
"legacyMarketplaces": [],
|
|
75
|
-
"contentHash": "sha256:
|
|
75
|
+
"contentHash": "sha256:2db5875a6f25f0c3321471c3ad099b3b6850e760a606d6b1bc53db672eb5a23b",
|
|
76
76
|
"description": "Set up and check PassionCode.ai on a computer with one command (setting-up-passioncode), 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.",
|
|
77
77
|
"author": {
|
|
78
78
|
"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; and teach a coding agent to work in a project through Fabric (fabric-mcp, fabric_whoami, claim and release), with Claude Code session hooks.",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.45.0",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "PassionCode.ai",
|
|
9
9
|
"url": "https://passioncode.ai/"
|
|
@@ -5,9 +5,9 @@ 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.
|
|
8
|
+
version: "0.45.0"
|
|
9
9
|
contract-version: "0.1.0"
|
|
10
|
-
contract-commit: "
|
|
10
|
+
contract-commit: "e742016dc396aa31e5a13a893489e43f15786c69"
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
# Adapting projects to Fabric
|
|
@@ -76,7 +76,7 @@ Use exactly:
|
|
|
76
76
|
|
|
77
77
|
- contract version `0.1.0`;
|
|
78
78
|
- repository `https://github.com/passioncode-ai/fabric-agent-contract`;
|
|
79
|
-
- commit `
|
|
79
|
+
- commit `e742016dc396aa31e5a13a893489e43f15786c69`.
|
|
80
80
|
|
|
81
81
|
This is the default for new bundles. When checking an issued legacy bundle, preserve its
|
|
82
82
|
explicit supported lock and use that exact clean checkout. Never silently upgrade or
|
|
@@ -22,10 +22,10 @@ import fabric_secrets as _secrets # noqa: E402 - the contract's credential dete
|
|
|
22
22
|
|
|
23
23
|
CONTRACT_VERSION = "0.1.0"
|
|
24
24
|
CONTRACT_REPOSITORY = "https://github.com/passioncode-ai/fabric-agent-contract"
|
|
25
|
-
CONTRACT_COMMIT = "
|
|
25
|
+
CONTRACT_COMMIT = "e742016dc396aa31e5a13a893489e43f15786c69"
|
|
26
26
|
# #region supported-contract-revisions — docs: README.md#contract-pin
|
|
27
27
|
# Only this declaration may name a legacy revision in live files.
|
|
28
|
-
SUPPORTED_CONTRACT_COMMITS = (CONTRACT_COMMIT, "c55f2d5a11c9a0197e958e87212fca7ae1154769", "07042181bfae2a481aa0da1a5651f24c76669c48", "d8146cfb0a1c74fc6432284c4356bb0c864b37b5", "82e163665e156a08aa3b92e4711015582c06162c", "1636fa97262f4a26e2086572d540c2ee701e0010", "f00a7685e3861c27f7899c033fb850a145a1708f", "a046f57cf46ea9e3da57ff8ce6a3ed4d26d8774b", "fe55fc67cba1a9e34a736da7d148d4fe2a8fbfa0", "b291bf09e0a9f9fd3c16cf540832cd021203b7d1", "0cacd08b0e95b6abf131eae1206b60792138bc3c", "2eb91c00e852d9c31d804310d38fad91589fcbac", "8e49fbd5fbbf230e32c1969cd24ac3c22422f0a5", "a83bec6b47776af688402c18efec507143061f68", "52da526d7cc1e063d74c5b520dbc03d0ace15246", "78b2da018d2c4bd9ac1bde1dc3b7f1a110a175f5", "623bf61358c339cb10297807b3f024b5d9f1f327", "23f9fda4c05f8a3852246ee98d4f2adf74ed0875", "9091d3d6606b0c4b5591a38c3674356a01fd7f55", "df55c8c54a23251342a7ee57ba95642b7eb39e61", "2ce392291c6668598d12cd38327e24696b5ca15c")
|
|
28
|
+
SUPPORTED_CONTRACT_COMMITS = (CONTRACT_COMMIT, "bfa9a67aa3c6cb808c093e7d83cd59799f1ee7d0", "c55f2d5a11c9a0197e958e87212fca7ae1154769", "07042181bfae2a481aa0da1a5651f24c76669c48", "d8146cfb0a1c74fc6432284c4356bb0c864b37b5", "82e163665e156a08aa3b92e4711015582c06162c", "1636fa97262f4a26e2086572d540c2ee701e0010", "f00a7685e3861c27f7899c033fb850a145a1708f", "a046f57cf46ea9e3da57ff8ce6a3ed4d26d8774b", "fe55fc67cba1a9e34a736da7d148d4fe2a8fbfa0", "b291bf09e0a9f9fd3c16cf540832cd021203b7d1", "0cacd08b0e95b6abf131eae1206b60792138bc3c", "2eb91c00e852d9c31d804310d38fad91589fcbac", "8e49fbd5fbbf230e32c1969cd24ac3c22422f0a5", "a83bec6b47776af688402c18efec507143061f68", "52da526d7cc1e063d74c5b520dbc03d0ace15246", "78b2da018d2c4bd9ac1bde1dc3b7f1a110a175f5", "623bf61358c339cb10297807b3f024b5d9f1f327", "23f9fda4c05f8a3852246ee98d4f2adf74ed0875", "9091d3d6606b0c4b5591a38c3674356a01fd7f55", "df55c8c54a23251342a7ee57ba95642b7eb39e61", "2ce392291c6668598d12cd38327e24696b5ca15c")
|
|
29
29
|
# #endregion supported-contract-revisions
|
|
30
30
|
INTEROP_KEY = "https://fabric.passioncode.ai/agent-contract/extensions/interop/0.1"
|
|
31
31
|
MCP_REVISION = "2026-07-28"
|
|
@@ -14,10 +14,10 @@ license: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
|
14
14
|
compatibility: Python 3.9+ or Node.js 20+ for the kits (Node.js 22+ for a Linux service's instance lock); the probe needs Python 3.9+. launchd steps are macOS-only; Linux services install a systemd user unit and Windows ones a per-user Scheduled Task with the kits' writers. Dashboard handoff optionally uses Fabric Dashboards MCP link/host_status/open; without it, report unresolved host capability. The contract checkout is optional.
|
|
15
15
|
metadata:
|
|
16
16
|
author: PassionCode.ai
|
|
17
|
-
version: "0.
|
|
17
|
+
version: "0.45.0"
|
|
18
18
|
contract-version: "0.1.0"
|
|
19
19
|
extension: "fabric-service/0.1"
|
|
20
|
-
extension-commit: "
|
|
20
|
+
extension-commit: "e742016dc396aa31e5a13a893489e43f15786c69"
|
|
21
21
|
---
|
|
22
22
|
|
|
23
23
|
# Building Fabric services
|
package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/references/board.md
CHANGED
|
@@ -117,7 +117,9 @@ spend sees it) is the service's own responsibility. A message never carries an a
|
|
|
117
117
|
| `idempotency_conflict` | a key sent with other content is a defect, not an outage: `board.blocked` (notify) naming it, and the session is left |
|
|
118
118
|
| in progress at a reconnect whose slot another session still holds | marked `unknown`; reconciled every five minutes once the slot is this session's |
|
|
119
119
|
|
|
120
|
-
On restart the checkpoint is read back: settled or
|
|
120
|
+
On restart the checkpoint is read back: settled, queued, claimed or `answered` requests are dropped (`answered`:
|
|
121
|
+
the target Project's participant reply answered it, DEC-0098 and DEC-0102; not settled, the requester may still cancel
|
|
122
|
+
it, but no longer this responder's); `in_progress` and `outcome_unknown` are
|
|
121
123
|
reconciled from what `observe(entry)` answers (observed only; with no observation they stay unknown and notify);
|
|
122
124
|
accepted ones go back to this responder with `com.responder_replace {expectedGeneration, transfer}`, whose receipt's
|
|
123
125
|
`transferred` (DEC-0078: `{request, revision, attempt}`) carries the new fence. **A Fabric that does not answer
|
|
@@ -80,7 +80,7 @@ then the grant check where there is one, then `verify_approval` / `verifyApprova
|
|
|
80
80
|
`jti` last, then the action. Without an approval, answer `approval-required` with
|
|
81
81
|
`action_digest(action)` / `actionDigest(action)` (the SHA-256 of the action's RFC 8785 form, `jcs`) so the caller
|
|
82
82
|
can ask the hub. When the meter denies a grant check, answer `refusal_from_denial(denial)` /
|
|
83
|
-
`refusalFromDenial(denial)`: the meter's code unchanged, its window and level in `error.data` (DL-21 step 6). Keep consumed ids in `FileJtiStore` (0600, survives a restart); `MemoryJtiStore` is for tests
|
|
83
|
+
`refusalFromDenial(denial)`: the meter's code unchanged, its window and level in `error.data` (DL-21 step 6). Keep consumed ids in `FileJtiStore` (owner-only through the kit's private writer: 0600, on Windows a protected ACL; survives a restart); `MemoryJtiStore` is for tests
|
|
84
84
|
and `UNSAFE_NO_JTI_STORE` exists only by name. No store at all, or a store file that cannot be read, is
|
|
85
85
|
`unknown-state`, never a pass.
|
|
86
86
|
|
|
@@ -54,15 +54,15 @@ A module imports only modules listed before it in `kit.json`, so the kit has no
|
|
|
54
54
|
| L0 | `fabric_identifiers` | identifier equality by normal form (DEC-0076) |
|
|
55
55
|
| L0 | `fabric_secrets` | the contract's one credential detector (DEC-0044) |
|
|
56
56
|
| L1 | `fabric_crypto` | Ed25519 signing (a Montgomery ladder that does not branch on the key) and verification, P-256 verification, base64url, sha256 |
|
|
57
|
+
| L1 | `fabric_base` | the protocol name, `ServiceError`, small shared helpers |
|
|
58
|
+
| L1 | `fabric_platform` | Windows: named pipes, owner-only files (DEC-0032) |
|
|
59
|
+
| L1 | `fabric_paths` | the services directory, a service's folders, atomic and private writes (L1 since 0.44.2, so `fabric_delegation` writes its consumed approval ids with them, FAA-85) |
|
|
57
60
|
| L2 | `fabric_estate` | `estate-record/1` revisions and their rules (DEC-0055) |
|
|
58
61
|
| L2 | `fabric_delegation` | the callee's side of `fabric-delegation/0.1` (DEC-0039) |
|
|
59
62
|
| L2 | `fabric_share` | share grants and registrations (DEC-0086) |
|
|
60
63
|
| L2 | `fabric_ceremonies` | the headless join token (DEC-0084) |
|
|
61
64
|
| L2 | `fabric_package_schema` | the reading of `fabric-package.schema.json` with JavaScript's pattern and format semantics (FAA-92) |
|
|
62
65
|
| L2 | `fabric_package` | `fabric-package/1`: pack, sign, verify; re-exports `schema_problems` (DEC-0050, DEC-0051) |
|
|
63
|
-
| L3 | `fabric_base` | the protocol name, `ServiceError`, small shared helpers |
|
|
64
|
-
| L3 | `fabric_platform` | Windows: named pipes, owner-only files (DEC-0032) |
|
|
65
|
-
| L3 | `fabric_paths` | the services directory, a service's folders, atomic and private writes |
|
|
66
66
|
| L3 | `fabric_protocols` | protocol revisions (DEC-0067) and feed data (DEC-0070) |
|
|
67
67
|
| L3 | `fabric_connections` | what an agent uses, `fabric-connections/0.1`: the reference reading and the declaration (DEC-0096, FAC-SEM-127) |
|
|
68
68
|
| L3 | `fabric_lock` | the instance lock and the supervisor marker (LC-01, DEC-0057) |
|
package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/references/protocol.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# fabric-service/0.1: wire reference
|
|
2
2
|
|
|
3
|
-
Pinned to `fabric-agent-contract` commit `
|
|
3
|
+
Pinned to `fabric-agent-contract` commit `e742016dc396aa31e5a13a893489e43f15786c69`
|
|
4
4
|
(`docs/specification/service.md`, DEC-0015; the usage report DEC-0021; Windows and Linux supervision
|
|
5
5
|
DEC-0032 and DEC-0033; the operator channel DEC-0034 and DEC-0035; the embedded dashboard DEC-0036;
|
|
6
6
|
delegation and the operator session's lifetime DEC-0039; the meter's call window DEC-0041; session handoff DEC-0042;
|
|
@@ -41,7 +41,7 @@ File `<id>.<instance>.json`, mode 0600 (on Windows a protected ACL), atomic.
|
|
|
41
41
|
| `source.repository`, `fabricManifest` | optional |
|
|
42
42
|
| `installedAt`, `installedBy` | when, and who installed it: the installer and its version as a string, or `{by, role?, tool}` (DEC-0061): `by` `person` (with `role` `operator` or `administrator`), `node` or `organization`; `role` for a person only; `tool` the installer and its version. It names a role, never a person. An app's descriptor uses the object form with `by: "person"`. `register_remote` / `registerRemote` and the sample write the object form |
|
|
43
43
|
| `runner` | optional `{kind?, credentialKind}` (DEC-0061): `credentialKind` `subscription`, `key`, `platform-metered` or `none`: a kind, never a credential (`FAC-SEM-086` refuses a credential-shaped value here or in `installedBy`); a subscription names its vendor's runner (`claude-code`, `kimi-code`, `codex`) |
|
|
44
|
-
| `peer` | optional `{endpoint, custody, residency, maxDataClass}` (DEC-0061): the service is offered to others. `endpoint` `https://<dns-name>[:<port>][/<path>]`, never a reserved name (`FAC-SEM-085`); `custody` `organization-managed` or `
|
|
44
|
+
| `peer` | optional `{endpoint, custody, residency, maxDataClass}` (DEC-0061): the service is offered to others. `endpoint` `https://<dns-name>[:<port>][/<path>]`, never a reserved name (`FAC-SEM-085`); `custody` `organization-managed`, `personal` or `processor-hosted` (an organization's cloud a processor runs under a processing agreement, DEC-0099); `residency` 1–32 ISO 3166-1 alpha-2 codes, `EU` admitted, user-assigned codes refused; `maxDataClass` `public` < `internal` < `confidential` < `restricted`. An offer needs `runner` and never runs on a subscription. A host sends a request from anyone but the operator only when `peer_refusal` / `peerRefusal` answers null (`FAC-SEM-088`); usage rows may take `route: "platform-metered"` |
|
|
45
45
|
|
|
46
46
|
## Identifier equality (DEC-0076)
|
|
47
47
|
|
package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-base.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// What every module of the Node service kit shares: the protocol name, ServiceError, ids, nowIso and expand.
|
|
2
|
-
// Part of the Node service kit (FAA-65, layer
|
|
2
|
+
// Part of the Node service kit (FAA-65, layer L1); the twin of fabric_base.py. Node 20+, no dependency.
|
|
3
3
|
import os from 'node:os';
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
|
|
@@ -22,6 +22,9 @@ export const EVENT_SCHEMA = 'urn:fabric:schema:board-responder-event:1';
|
|
|
22
22
|
export const STOP_CODES = Object.freeze(new Set(['fenced', 'lease_expired', 'authority_changed']));
|
|
23
23
|
|
|
24
24
|
const TERMINAL = new Set(['completed', 'failed_known', 'cancelled', 'expired']);
|
|
25
|
+
// No longer this responder's to work on: back in the queue, claimed again, or answered by the target Project's
|
|
26
|
+
// participant reply (DEC-0098, DEC-0102; not terminal, the requester may still cancel it, and nobody claims it).
|
|
27
|
+
const NOT_OURS = new Set(['queued', 'claimed', 'answered']);
|
|
25
28
|
|
|
26
29
|
/** A lost call is sent again this long before the lease it keeps would lapse (FAA-77, finding 38). */
|
|
27
30
|
export const LEASE_MARGIN_SECONDS = 10;
|
|
@@ -226,7 +229,7 @@ export class Responder {
|
|
|
226
229
|
}
|
|
227
230
|
throw e;
|
|
228
231
|
}
|
|
229
|
-
if (state === null || TERMINAL.has(state) || state
|
|
232
|
+
if (state === null || TERMINAL.has(state) || NOT_OURS.has(state)) this.checkpoint.drop(entry.request);
|
|
230
233
|
else if (state === 'accepted') (transfer[entry.capability] ??= []).push(entry);
|
|
231
234
|
else reconcile.push(entry);
|
|
232
235
|
}
|
|
@@ -348,7 +351,7 @@ export class Responder {
|
|
|
348
351
|
async reconcile(entry) {
|
|
349
352
|
const state = await this.readState(entry);
|
|
350
353
|
if (state !== 'outcome_unknown') {
|
|
351
|
-
if (state !== null && (TERMINAL.has(state) || state
|
|
354
|
+
if (state !== null && (TERMINAL.has(state) || NOT_OURS.has(state))) this.checkpoint.drop(entry.request);
|
|
352
355
|
else if (state === 'in_progress' && entry.step !== 'unknown') {
|
|
353
356
|
entry.step = 'unknown'; // no next holder took the slot yet: a later tick tries again (finding 38)
|
|
354
357
|
this.checkpoint.put(entry);
|
|
@@ -39,7 +39,8 @@ export const REFUSAL_CODES = Object.freeze(new Set(['invalid_arguments', 'body_t
|
|
|
39
39
|
'capacity_exceeded', 'digest_conflict', 'revision_conflict', 'fenced', 'lease_expired', 'invalid_transition', 'reconcile_required',
|
|
40
40
|
'observation_required', 'cursor_reset_required', 'immutable_participants', 'held']));
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
// answered (DEC-0098, DEC-0102): the target Project's participant message answered it; never a responder's fenced reply.
|
|
43
|
+
export const REQUEST_STATES = ['queued', 'claimed', 'accepted', 'in_progress', 'completed', 'failed_known', 'cancelled', 'expired', 'outcome_unknown', 'answered'];
|
|
43
44
|
|
|
44
45
|
const EFFECT_STATES = ['not_started', 'started', 'succeeded_observed', 'failed_observed', 'unknown'];
|
|
45
46
|
|
|
@@ -139,7 +140,7 @@ function attemptProblems(a, at, problems) {
|
|
|
139
140
|
/** comms-receipt at the pin, closed at every level; transferred answers com.responder_replace only, each request once. */
|
|
140
141
|
export function receiptProblems(value, op) {
|
|
141
142
|
const problems = [];
|
|
142
|
-
const allowed = ['ok', 'repeated', 'message', 'thread', 'at', 'request', 'slot', 'attempt', 'transferred'];
|
|
143
|
+
const allowed = ['ok', 'repeated', 'message', 'thread', 'at', 'request', 'slot', 'attempt', 'transferred', 'marked', 'alreadyRead', 'more', 'noResponder'];
|
|
143
144
|
if (!closed(value, '', ['ok', 'repeated'], allowed, problems)) return problems;
|
|
144
145
|
if (value.ok !== true) problems.push('/ok is true');
|
|
145
146
|
if (typeof value.repeated !== 'boolean') problems.push('/repeated is a boolean');
|
|
@@ -189,6 +190,21 @@ export function receiptProblems(value, op) {
|
|
|
189
190
|
});
|
|
190
191
|
}
|
|
191
192
|
}
|
|
193
|
+
// DEC-0098: a bulk com.read_ack counts what it marked; `more` is present only as true (more than 1000 qualified).
|
|
194
|
+
for (const k of ['marked', 'alreadyRead']) if (k in value && !isInt(value[k], 0)) problems.push(`/${k} is an integer ≥ 0`);
|
|
195
|
+
if ('more' in value && value.more !== true) problems.push('/more is true when present');
|
|
196
|
+
if (op !== undefined && ['marked', 'alreadyRead', 'more'].some((k) => k in value) && op !== 'com.read_ack') problems.push('/marked, /alreadyRead and /more answer com.read_ack only (DEC-0098)');
|
|
197
|
+
if ('noResponder' in value) {
|
|
198
|
+
// DEC-0098: only in the requester's own com.submit receipt for a request; the request is stored all the same.
|
|
199
|
+
const n = value.noResponder;
|
|
200
|
+
if (op !== undefined && op !== 'com.submit') problems.push('/noResponder answers com.submit only (DEC-0098)');
|
|
201
|
+
const keys = ['target', 'capability', 'message'];
|
|
202
|
+
if (closed(n, '/noResponder', keys, keys, problems)) {
|
|
203
|
+
if (!str(n.target, PROJECT)) problems.push('/noResponder/target is a Project id');
|
|
204
|
+
if (!str(n.capability, CAPABILITY)) problems.push('/noResponder/capability is a capability name');
|
|
205
|
+
if (!(typeof n.message === 'string' && [...n.message].length >= 1 && [...n.message].length <= 300)) problems.push('/noResponder/message is 1 to 300 characters');
|
|
206
|
+
}
|
|
207
|
+
}
|
|
192
208
|
return problems;
|
|
193
209
|
}
|
|
194
210
|
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
import crypto from 'node:crypto';
|
|
14
14
|
import fs from 'node:fs';
|
|
15
15
|
import net from 'node:net';
|
|
16
|
-
import path from 'node:path';
|
|
17
16
|
import { hubKeyCertified } from './fabric-estate.mjs';
|
|
17
|
+
import { atomicWrite } from './fabric-paths.mjs'; // the kit's private writer (FAA-85)
|
|
18
18
|
|
|
19
19
|
export const REFUSAL_CODES = Object.freeze([
|
|
20
20
|
'unauthenticated', 'token-expired', 'wrong-audience', 'scope-not-granted', 'effect-above-ceiling', 'no-grant',
|
|
@@ -347,7 +347,7 @@ export function createMemoryJtiStore() {
|
|
|
347
347
|
export class JtiStoreError extends Error {}
|
|
348
348
|
|
|
349
349
|
/**
|
|
350
|
-
* Consumed approval ids in
|
|
350
|
+
* Consumed approval ids in an owner-only JSON file, so a second use is refused across a restart (DL-18). A file that
|
|
351
351
|
* cannot be read throws JtiStoreError: forgetting every consumed id would let each approval be replayed.
|
|
352
352
|
*/
|
|
353
353
|
export class FileJtiStore {
|
|
@@ -364,11 +364,9 @@ export class FileJtiStore {
|
|
|
364
364
|
const seen = new Map(Object.entries(read).filter(([, until]) => typeof until === 'number' && until + LEEWAY_SECONDS >= now));
|
|
365
365
|
if (seen.has(jti)) return false;
|
|
366
366
|
seen.set(jti, expiresAt);
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
try { fs.writeSync(fd, JSON.stringify(Object.fromEntries(seen))); fs.fsyncSync(fd); } finally { fs.closeSync(fd); }
|
|
371
|
-
fs.renameSync(temp, this.file);
|
|
367
|
+
// Owner-only (0600; on Windows a protected ACL before the bytes, DEC-0032), fsynced, renamed into place, and no
|
|
368
|
+
// temporary file left when it fails (FAA-85).
|
|
369
|
+
atomicWrite(this.file, JSON.stringify(Object.fromEntries(seen)));
|
|
372
370
|
return true;
|
|
373
371
|
}
|
|
374
372
|
}
|
|
@@ -174,7 +174,7 @@ export function descriptorMemberProblems(d) {
|
|
|
174
174
|
const m = typeof peer.endpoint === 'string' && peer.endpoint.length <= 2048 ? PEER_ENDPOINT.exec(peer.endpoint) : null;
|
|
175
175
|
if (!m) problems.push('peer.endpoint is https://<dns-name>[:<port>][/<path>], no query, fragment, userinfo or IP literal');
|
|
176
176
|
else if (RESERVED_HOST.test(m[1])) problems.push(`FAC-SEM-085: a service offered to others cannot be reached at the reserved name ${m[1]}`);
|
|
177
|
-
if (!['organization-managed', 'personal'].includes(peer.custody)) problems.push('peer.custody is organization-managed or
|
|
177
|
+
if (!['organization-managed', 'personal', 'processor-hosted'].includes(peer.custody)) problems.push('peer.custody is organization-managed, personal or processor-hosted'); // processor-hosted: DEC-0099
|
|
178
178
|
const r = peer.residency;
|
|
179
179
|
if (!Array.isArray(r) || r.length < 1 || r.length > 32 || new Set(r.map((x) => JSON.stringify(x))).size !== r.length || !r.every((x) => typeof x === 'string' && RESIDENCY.test(x))) {
|
|
180
180
|
problems.push('peer.residency is 1 to 32 distinct ISO 3166-1 alpha-2 codes in upper case, EU admitted, no user-assigned code');
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Where a service's things live (fabric-service/0.1): the services directory, its data, config, logs and run dirs per OS, private dirs, atomic writes.
|
|
2
|
-
// Part of the Node service kit (FAA-65, layer
|
|
2
|
+
// Part of the Node service kit (FAA-65, layer L1); the twin of fabric_paths.py. Node 20+, no dependency.
|
|
3
3
|
import crypto from 'node:crypto';
|
|
4
4
|
import fs from 'node:fs';
|
|
5
5
|
import os from 'node:os';
|
|
@@ -51,19 +51,21 @@ export function atomicWrite(file, data, mode = 0o600) {
|
|
|
51
51
|
const tmp = path.join(path.dirname(file), `.${path.basename(file)}.${process.pid}.${crypto.randomBytes(4).toString('hex')}`);
|
|
52
52
|
const fd = fs.openSync(tmp, 'wx', mode);
|
|
53
53
|
try {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
54
|
+
try {
|
|
55
|
+
// On Windows the file's ACL is its privacy (DEC-0032): set explicitly and protected — before the bytes go in —
|
|
56
|
+
// so it does not depend on what the folder hands down. A rename keeps it.
|
|
57
|
+
if (process.platform === 'win32') windowsProtect(tmp, { folder: false });
|
|
58
|
+
fs.writeSync(fd, data);
|
|
59
|
+
fs.fsyncSync(fd);
|
|
60
|
+
} finally {
|
|
61
|
+
fs.closeSync(fd);
|
|
62
|
+
}
|
|
63
63
|
if (process.platform !== 'win32') fs.chmodSync(tmp, mode);
|
|
64
64
|
fs.renameSync(tmp, file);
|
|
65
65
|
} catch (error) {
|
|
66
|
-
|
|
66
|
+
// Whatever failed, no half-written file is left beside the real one, and a failed cleanup never replaces the
|
|
67
|
+
// error that caused it (FAA-85).
|
|
68
|
+
try { fs.rmSync(tmp, { force: true }); } catch { /* the original error is the one to report */ }
|
|
67
69
|
throw error;
|
|
68
70
|
}
|
|
69
71
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Windows, where the kit needs it (DEC-0032): reading a file's ACL to refuse a token file others can read.
|
|
2
|
-
// Part of the Node service kit (FAA-65, layer
|
|
2
|
+
// Part of the Node service kit (FAA-65, layer L1); the twin of fabric_platform.py. Node 20+, no dependency.
|
|
3
3
|
import crypto from 'node:crypto';
|
|
4
4
|
import fs from 'node:fs';
|
|
5
5
|
import os from 'node:os';
|
|
@@ -12,7 +12,8 @@ export const PROTOCOL_REVISIONS = new Map(Object.entries({
|
|
|
12
12
|
'fabric-interop': ['0.1', '0.2'], 'fabric-local-channel': ['0.1'], 'fabric-local-runner': ['0.1'], 'fabric-operator-channel': ['0.1'],
|
|
13
13
|
'fabric-package': ['1'], 'fabric-project-comms': ['0.1'], 'fabric-proposal': ['1'], 'fabric-provider': ['0.1'], 'fabric-relay': ['0.1'],
|
|
14
14
|
'fabric-secret-envelope': ['1'], 'fabric-service': ['0.1'], 'fabric-settings-backup': ['1'], heartbeat: ['1'], 'learning-note': ['1'],
|
|
15
|
-
memory: ['0.1'], 'pairing-message': ['1'], pipeline: ['0.1'], '
|
|
15
|
+
memory: ['0.1'], 'node-summary': ['1'], 'pairing-message': ['1'], pipeline: ['0.1'], 'repair-request': ['1'], 'repair-result': ['1'],
|
|
16
|
+
'revocation-delta': ['1'], 'session-handoff': ['1'],
|
|
16
17
|
'share-registration': ['1'], 'share-registration-receipt': ['1'], 'support-quality-daily': ['1'], 'window-lease': ['1'],
|
|
17
18
|
}));
|
|
18
19
|
|
package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_base.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""What every module of the service kit shares (FAA-65, layer
|
|
1
|
+
"""What every module of the service kit shares (FAA-65, layer L1): the protocol name, ServiceError, the
|
|
2
2
|
platform, ids and now_iso. Standard library only."""
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
@@ -61,6 +61,9 @@ STOP_CODES = frozenset(["fenced", "lease_expired", "authority_changed"])
|
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
TERMINAL = frozenset(["completed", "failed_known", "cancelled", "expired"])
|
|
64
|
+
#: No longer this responder's to work on: back in the queue, claimed again, or answered by the target Project's
|
|
65
|
+
#: participant reply (DEC-0098, DEC-0102; not terminal, the requester may still cancel it, and nobody claims it).
|
|
66
|
+
NOT_OURS = frozenset(["queued", "claimed", "answered"])
|
|
64
67
|
|
|
65
68
|
|
|
66
69
|
#: A lost call is sent again this long before the lease it keeps would lapse (FAA-77, finding 38).
|
|
@@ -283,8 +286,8 @@ class Responder:
|
|
|
283
286
|
self.checkpoint.drop(entry["request"])
|
|
284
287
|
continue
|
|
285
288
|
raise
|
|
286
|
-
if state is None or state in TERMINAL or state in
|
|
287
|
-
self.checkpoint.drop(entry["request"]) # settled, or
|
|
289
|
+
if state is None or state in TERMINAL or state in NOT_OURS:
|
|
290
|
+
self.checkpoint.drop(entry["request"]) # settled, or no longer this responder's (NOT_OURS)
|
|
288
291
|
elif state == "accepted":
|
|
289
292
|
transfer.setdefault(entry["capability"], []).append(entry)
|
|
290
293
|
else: # in_progress (lost result once a new generation holds the slot) or outcome_unknown
|
|
@@ -401,7 +404,7 @@ class Responder:
|
|
|
401
404
|
def _reconcile(self, entry: Dict[str, Any]) -> None:
|
|
402
405
|
state = self._read_state(entry)
|
|
403
406
|
if state != "outcome_unknown":
|
|
404
|
-
if state in TERMINAL or state in
|
|
407
|
+
if state in TERMINAL or state in NOT_OURS:
|
|
405
408
|
self.checkpoint.drop(entry["request"])
|
|
406
409
|
elif state == "in_progress" and entry.get("step") != "unknown":
|
|
407
410
|
entry["step"] = "unknown" # no next holder took the slot yet: a later tick tries again (finding 38)
|
|
@@ -46,8 +46,9 @@ REFUSAL_CODES = frozenset(["invalid_arguments", "body_too_large", "not_authorize
|
|
|
46
46
|
"cursor_reset_required", "immutable_participants", "held"])
|
|
47
47
|
|
|
48
48
|
|
|
49
|
+
#: answered (DEC-0098, DEC-0102): the target Project's participant message answered it; never a responder's fenced reply.
|
|
49
50
|
REQUEST_STATES = ("queued", "claimed", "accepted", "in_progress", "completed", "failed_known", "cancelled", "expired",
|
|
50
|
-
"outcome_unknown")
|
|
51
|
+
"outcome_unknown", "answered")
|
|
51
52
|
|
|
52
53
|
|
|
53
54
|
EFFECT_STATES = ("not_started", "started", "succeeded_observed", "failed_observed", "unknown")
|
|
@@ -176,7 +177,8 @@ def receipt_problems(value: Any, op: Optional[str] = None) -> List[str]:
|
|
|
176
177
|
"""`comms-receipt.schema.json` at the pin, closed at every level (a seq or a holder is refused, C3), plus what a
|
|
177
178
|
schema cannot say: `transferred` answers only `com.responder_replace` (DEC-0078) and names each request once."""
|
|
178
179
|
problems: List[str] = []
|
|
179
|
-
allowed = ("ok", "repeated", "message", "thread", "at", "request", "slot", "attempt", "transferred"
|
|
180
|
+
allowed = ("ok", "repeated", "message", "thread", "at", "request", "slot", "attempt", "transferred", "marked",
|
|
181
|
+
"alreadyRead", "more", "noResponder")
|
|
180
182
|
if not _closed(value, "", ("ok", "repeated"), allowed, problems):
|
|
181
183
|
return problems
|
|
182
184
|
if value.get("ok") is not True:
|
|
@@ -241,6 +243,27 @@ def receipt_problems(value: Any, op: Optional[str] = None) -> List[str]:
|
|
|
241
243
|
if not _is_int(item.get("revision"), 1):
|
|
242
244
|
problems.append("%s/revision is an integer ≥ 1" % at)
|
|
243
245
|
_attempt_problems(item.get("attempt"), at + "/attempt", problems)
|
|
246
|
+
# DEC-0098: a bulk com.read_ack counts what it marked; `more` is present only as true (more than 1000 qualified).
|
|
247
|
+
for key in ("marked", "alreadyRead"):
|
|
248
|
+
if key in value and not _is_int(value[key], 0):
|
|
249
|
+
problems.append("/%s is an integer ≥ 0" % key)
|
|
250
|
+
if "more" in value and value["more"] is not True:
|
|
251
|
+
problems.append("/more is true when present")
|
|
252
|
+
if op is not None and any(k in value for k in ("marked", "alreadyRead", "more")) and op != "com.read_ack":
|
|
253
|
+
problems.append("/marked, /alreadyRead and /more answer com.read_ack only (DEC-0098)")
|
|
254
|
+
if "noResponder" in value:
|
|
255
|
+
# DEC-0098: only in the requester's own com.submit receipt for a request; the request is stored all the same.
|
|
256
|
+
n = value["noResponder"]
|
|
257
|
+
if op is not None and op != "com.submit":
|
|
258
|
+
problems.append("/noResponder answers com.submit only (DEC-0098)")
|
|
259
|
+
keys = ("target", "capability", "message")
|
|
260
|
+
if _closed(n, "/noResponder", keys, keys, problems):
|
|
261
|
+
if not (isinstance(n.get("target"), str) and _PROJECT.fullmatch(n["target"])):
|
|
262
|
+
problems.append("/noResponder/target is a Project id")
|
|
263
|
+
if not (isinstance(n.get("capability"), str) and _CAPABILITY.fullmatch(n["capability"])):
|
|
264
|
+
problems.append("/noResponder/capability is a capability name")
|
|
265
|
+
if not (isinstance(n.get("message"), str) and 1 <= len(n["message"]) <= 300):
|
|
266
|
+
problems.append("/noResponder/message is 1 to 300 characters")
|
|
244
267
|
return problems
|
|
245
268
|
|
|
246
269
|
|
|
@@ -21,10 +21,8 @@ import http.client
|
|
|
21
21
|
import ipaddress
|
|
22
22
|
import json
|
|
23
23
|
import math
|
|
24
|
-
import os
|
|
25
24
|
from pathlib import Path
|
|
26
25
|
import re
|
|
27
|
-
import secrets
|
|
28
26
|
import threading
|
|
29
27
|
import time
|
|
30
28
|
from typing import Any, Callable, Dict, List, Mapping, Optional, Tuple
|
|
@@ -46,6 +44,7 @@ from fabric_jsvalue import ( # noqa: E402 - the core (FAA-65)
|
|
|
46
44
|
MISSING as _MISSING,
|
|
47
45
|
jcs,
|
|
48
46
|
)
|
|
47
|
+
from fabric_paths import atomic_write as _atomic_write # noqa: E402 - the kit's private writer (FAA-85)
|
|
49
48
|
|
|
50
49
|
REFUSAL_CODES = (
|
|
51
50
|
"unauthenticated", "token-expired", "wrong-audience", "scope-not-granted", "effect-above-ceiling", "no-grant",
|
|
@@ -484,7 +483,7 @@ class JtiStoreError(RuntimeError):
|
|
|
484
483
|
|
|
485
484
|
|
|
486
485
|
class FileJtiStore:
|
|
487
|
-
"""Consumed approval ids in
|
|
486
|
+
"""Consumed approval ids in an owner-only JSON file, so a second use is refused across a restart (DL-18). One
|
|
488
487
|
service instance writes it (the kit's instance lock keeps other processes out); threads are serialised."""
|
|
489
488
|
|
|
490
489
|
_locks: Dict[str, threading.Lock] = {}
|
|
@@ -511,14 +510,9 @@ class FileJtiStore:
|
|
|
511
510
|
if jti in seen:
|
|
512
511
|
return False
|
|
513
512
|
seen[jti] = expires_at
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
with os.fdopen(fd, "w") as handle:
|
|
518
|
-
json.dump(seen, handle)
|
|
519
|
-
handle.flush()
|
|
520
|
-
os.fsync(handle.fileno())
|
|
521
|
-
os.replace(str(temp), str(self.path))
|
|
513
|
+
# The kit's private writer: owner-only (0600; on Windows a protected ACL before the bytes, DEC-0032),
|
|
514
|
+
# fsynced, renamed into place, and no temporary file left when it fails (FAA-85).
|
|
515
|
+
_atomic_write(self.path, json.dumps(seen).encode("utf-8"))
|
|
522
516
|
return True
|
|
523
517
|
|
|
524
518
|
|
|
@@ -285,8 +285,8 @@ def descriptor_member_problems(descriptor: Dict[str, Any]) -> List[str]:
|
|
|
285
285
|
problems.append("peer.endpoint is https://<dns-name>[:<port>][/<path>], no query, fragment, userinfo or IP literal")
|
|
286
286
|
elif _RESERVED_HOST.search(match.group("host")):
|
|
287
287
|
problems.append("FAC-SEM-085: a service offered to others cannot be reached at the reserved name %s" % match.group("host"))
|
|
288
|
-
if peer.get("custody") not in ("organization-managed", "personal"):
|
|
289
|
-
problems.append("peer.custody is organization-managed or
|
|
288
|
+
if peer.get("custody") not in ("organization-managed", "personal", "processor-hosted"): # processor-hosted: DEC-0099
|
|
289
|
+
problems.append("peer.custody is organization-managed, personal or processor-hosted")
|
|
290
290
|
residency = peer.get("residency")
|
|
291
291
|
if (not isinstance(residency, list) or not 1 <= len(residency) <= 32 or len(set(map(json.dumps, residency))) != len(residency)
|
|
292
292
|
or not all(isinstance(r, str) and _RESIDENCY.match(r) for r in residency)):
|
package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_paths.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""Where a service's things live (fabric-service/0.1): the services directory, a service's data, config, logs and run
|
|
2
|
-
directories per OS, private directories and atomic writes. Part of the service kit (FAA-65, layer
|
|
2
|
+
directories per OS, private directories and atomic writes. Part of the service kit (FAA-65, layer L1)."""
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import os
|
|
@@ -83,11 +83,11 @@ def atomic_write(path: Path, data: bytes, mode: int = 0o600) -> None:
|
|
|
83
83
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
84
84
|
fd, tmp = tempfile.mkstemp(prefix="." + path.name + ".", dir=str(path.parent))
|
|
85
85
|
try:
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
with os.fdopen(fd, "wb") as handle: # closed on every path: Windows cannot delete a file still open
|
|
87
|
+
if WINDOWS:
|
|
88
|
+
# The file's ACL is its privacy (DEC-0032): set explicitly and protected — before the bytes go in —
|
|
89
|
+
# so it does not depend on what the folder hands down. A rename keeps it.
|
|
90
|
+
_win_protect(Path(tmp), folder=False)
|
|
91
91
|
handle.write(data)
|
|
92
92
|
handle.flush()
|
|
93
93
|
os.fsync(handle.fileno())
|
|
@@ -97,6 +97,6 @@ def atomic_write(path: Path, data: bytes, mode: int = 0o600) -> None:
|
|
|
97
97
|
except BaseException:
|
|
98
98
|
try:
|
|
99
99
|
os.unlink(tmp)
|
|
100
|
-
except
|
|
101
|
-
pass
|
|
100
|
+
except OSError:
|
|
101
|
+
pass # the error that got us here is the one to report, not a failed cleanup (FAA-85)
|
|
102
102
|
raise
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Windows, where the kit needs it (DEC-0032): named pipes that hold one copy, protecting a file to its owner, and
|
|
2
2
|
reading a file's ACL to refuse a token file others can read. On other systems the same names exist and do nothing
|
|
3
|
-
or answer "absent". Part of the service kit (FAA-65, layer
|
|
3
|
+
or answer "absent". Part of the service kit (FAA-65, layer L1)."""
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
6
|
import os
|
|
@@ -19,8 +19,8 @@ PROTOCOL_REVISIONS: Dict[str, Tuple[str, ...]] = {
|
|
|
19
19
|
"fabric-interop": ("0.1", "0.2"), "fabric-local-channel": ("0.1",), "fabric-local-runner": ("0.1",),
|
|
20
20
|
"fabric-operator-channel": ("0.1",), "fabric-package": ("1",), "fabric-project-comms": ("0.1",), "fabric-proposal": ("1",),
|
|
21
21
|
"fabric-provider": ("0.1",), "fabric-relay": ("0.1",), "fabric-secret-envelope": ("1",), "fabric-service": ("0.1",),
|
|
22
|
-
"fabric-settings-backup": ("1",), "heartbeat": ("1",), "learning-note": ("1",), "memory": ("0.1",), "
|
|
23
|
-
"revocation-delta": ("1",), "session-handoff": ("1",), "share-registration": ("1",),
|
|
22
|
+
"fabric-settings-backup": ("1",), "heartbeat": ("1",), "learning-note": ("1",), "memory": ("0.1",), "node-summary": ("1",), "pairing-message": ("1",),
|
|
23
|
+
"pipeline": ("0.1",), "repair-request": ("1",), "repair-result": ("1",), "revocation-delta": ("1",), "session-handoff": ("1",), "share-registration": ("1",),
|
|
24
24
|
"share-registration-receipt": ("1",), "support-quality-daily": ("1",), "window-lease": ("1",),
|
|
25
25
|
}
|
|
26
26
|
|
package/payload/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/kit.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fabric-service-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.45.0",
|
|
4
4
|
"about": "The service kit's modules in dependency order: a module imports only modules listed before it. Written by fabric_kit.py build; edit the order and layers by hand, never the digests.",
|
|
5
5
|
"python": [
|
|
6
6
|
{
|
|
@@ -40,6 +40,32 @@
|
|
|
40
40
|
"imports": [],
|
|
41
41
|
"sha256": "9c34aee20dbe4d6742e4fdbaab68ceb934bbe7dbd3a904c0010824ace16cdeaa"
|
|
42
42
|
},
|
|
43
|
+
{
|
|
44
|
+
"module": "fabric_base",
|
|
45
|
+
"file": "fabric_base.py",
|
|
46
|
+
"layer": "L1",
|
|
47
|
+
"imports": [],
|
|
48
|
+
"sha256": "f62bcc2ed9912660fa875d27a09f60867260cc4925f79873501fd9620be59611"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"module": "fabric_platform",
|
|
52
|
+
"file": "fabric_platform.py",
|
|
53
|
+
"layer": "L1",
|
|
54
|
+
"imports": [
|
|
55
|
+
"fabric_base"
|
|
56
|
+
],
|
|
57
|
+
"sha256": "a9350dff55ef0fb3a23cdb4d0320a15868b15a8deb10d2eb74d72c58740c284b"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"module": "fabric_paths",
|
|
61
|
+
"file": "fabric_paths.py",
|
|
62
|
+
"layer": "L1",
|
|
63
|
+
"imports": [
|
|
64
|
+
"fabric_base",
|
|
65
|
+
"fabric_platform"
|
|
66
|
+
],
|
|
67
|
+
"sha256": "6c92af34292baddf7e10d3134d0a5b0bb23387741812a9f79c409cf1628bad23"
|
|
68
|
+
},
|
|
43
69
|
{
|
|
44
70
|
"module": "fabric_estate",
|
|
45
71
|
"file": "fabric_estate.py",
|
|
@@ -60,9 +86,10 @@
|
|
|
60
86
|
"imports": [
|
|
61
87
|
"fabric_crypto",
|
|
62
88
|
"fabric_estate",
|
|
63
|
-
"fabric_jsvalue"
|
|
89
|
+
"fabric_jsvalue",
|
|
90
|
+
"fabric_paths"
|
|
64
91
|
],
|
|
65
|
-
"sha256": "
|
|
92
|
+
"sha256": "4eb5004188fdc6f5c0fd21fb0f9f1f538899a0383bcde0365dea080ef8347182"
|
|
66
93
|
},
|
|
67
94
|
{
|
|
68
95
|
"module": "fabric_share",
|
|
@@ -116,32 +143,6 @@
|
|
|
116
143
|
],
|
|
117
144
|
"sha256": "ff533f1b3f92b4ea0f532fcec50b68c610d47549930eef8ad5247692a64dfb3c"
|
|
118
145
|
},
|
|
119
|
-
{
|
|
120
|
-
"module": "fabric_base",
|
|
121
|
-
"file": "fabric_base.py",
|
|
122
|
-
"layer": "L3",
|
|
123
|
-
"imports": [],
|
|
124
|
-
"sha256": "684533b3a2aa3acd9b9e645a7a443427d279408f9f12f13456a0a991d57954ce"
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
"module": "fabric_platform",
|
|
128
|
-
"file": "fabric_platform.py",
|
|
129
|
-
"layer": "L3",
|
|
130
|
-
"imports": [
|
|
131
|
-
"fabric_base"
|
|
132
|
-
],
|
|
133
|
-
"sha256": "8b0cd89193bc55da204a4a1850665c96929c6778523a8715b8156c5643745288"
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
"module": "fabric_paths",
|
|
137
|
-
"file": "fabric_paths.py",
|
|
138
|
-
"layer": "L3",
|
|
139
|
-
"imports": [
|
|
140
|
-
"fabric_base",
|
|
141
|
-
"fabric_platform"
|
|
142
|
-
],
|
|
143
|
-
"sha256": "0d87e572bde2b930391b27aa370d808e093ce45cfba6148706f5318219906d30"
|
|
144
|
-
},
|
|
145
146
|
{
|
|
146
147
|
"module": "fabric_protocols",
|
|
147
148
|
"file": "fabric_protocols.py",
|
|
@@ -149,7 +150,7 @@
|
|
|
149
150
|
"imports": [
|
|
150
151
|
"fabric_secrets"
|
|
151
152
|
],
|
|
152
|
-
"sha256": "
|
|
153
|
+
"sha256": "0d58251ce5f36c8f6372f8e38719543166833399078f824804430b2e070b11f6"
|
|
153
154
|
},
|
|
154
155
|
{
|
|
155
156
|
"module": "fabric_connections",
|
|
@@ -208,7 +209,7 @@
|
|
|
208
209
|
"fabric_secrets",
|
|
209
210
|
"fabric_usage"
|
|
210
211
|
],
|
|
211
|
-
"sha256": "
|
|
212
|
+
"sha256": "64acadc3bbf6e1f95ff275344a7a1fa8b53809e725cd3305a0832a968e7403e9"
|
|
212
213
|
},
|
|
213
214
|
{
|
|
214
215
|
"module": "fabric_auth",
|
|
@@ -331,7 +332,7 @@
|
|
|
331
332
|
"imports": [
|
|
332
333
|
"fabric_identifiers"
|
|
333
334
|
],
|
|
334
|
-
"sha256": "
|
|
335
|
+
"sha256": "0a0e8d3d40e33dfd8c457aedb85330b2ff25f8c49a33eb6cbd5a5cc8a5007f7e"
|
|
335
336
|
},
|
|
336
337
|
{
|
|
337
338
|
"module": "fabric_board_link",
|
|
@@ -354,7 +355,7 @@
|
|
|
354
355
|
"fabric_hub",
|
|
355
356
|
"fabric_service"
|
|
356
357
|
],
|
|
357
|
-
"sha256": "
|
|
358
|
+
"sha256": "2271834c36c23f6bfa50395cd147e6af99f294ef09325fd15f0759ca8e18d941"
|
|
358
359
|
},
|
|
359
360
|
{
|
|
360
361
|
"module": "fabric_board_fixture",
|
|
@@ -435,6 +436,32 @@
|
|
|
435
436
|
"imports": [],
|
|
436
437
|
"sha256": "038e03689701e3c9721a1e7f8e0a4d02a52d6a5d1661b0dc84035edc3ebbfcf6"
|
|
437
438
|
},
|
|
439
|
+
{
|
|
440
|
+
"module": "fabric-base",
|
|
441
|
+
"file": "fabric-base.mjs",
|
|
442
|
+
"layer": "L1",
|
|
443
|
+
"imports": [],
|
|
444
|
+
"sha256": "7804b2df7715dbbf9702a9b61b6b8cef2110f9a52b04cabd8fb0a66458d87512"
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
"module": "fabric-platform",
|
|
448
|
+
"file": "fabric-platform.mjs",
|
|
449
|
+
"layer": "L1",
|
|
450
|
+
"imports": [
|
|
451
|
+
"fabric-base"
|
|
452
|
+
],
|
|
453
|
+
"sha256": "a8119d95ebba4d589a9e401f5d6fc8dda62d59d44e4c1ff811d97fac3771ac0c"
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
"module": "fabric-paths",
|
|
457
|
+
"file": "fabric-paths.mjs",
|
|
458
|
+
"layer": "L1",
|
|
459
|
+
"imports": [
|
|
460
|
+
"fabric-base",
|
|
461
|
+
"fabric-platform"
|
|
462
|
+
],
|
|
463
|
+
"sha256": "2201b4ed7126f260931b63e8386377b4317d8dcad419d109bf22c683e44b7f29"
|
|
464
|
+
},
|
|
438
465
|
{
|
|
439
466
|
"module": "fabric-estate",
|
|
440
467
|
"file": "fabric-estate.mjs",
|
|
@@ -455,9 +482,10 @@
|
|
|
455
482
|
"imports": [
|
|
456
483
|
"fabric-crypto",
|
|
457
484
|
"fabric-estate",
|
|
458
|
-
"fabric-jsvalue"
|
|
485
|
+
"fabric-jsvalue",
|
|
486
|
+
"fabric-paths"
|
|
459
487
|
],
|
|
460
|
-
"sha256": "
|
|
488
|
+
"sha256": "85a7e00e606244e7e02f9cbecc3e421bfcb9c1e12cd2a91daadf8a9c2403104d"
|
|
461
489
|
},
|
|
462
490
|
{
|
|
463
491
|
"module": "fabric-share",
|
|
@@ -509,32 +537,6 @@
|
|
|
509
537
|
],
|
|
510
538
|
"sha256": "49b757eefcc50e4c91585d5a5694bf3c83d0b03d112c1837f1c9f01466797ab5"
|
|
511
539
|
},
|
|
512
|
-
{
|
|
513
|
-
"module": "fabric-base",
|
|
514
|
-
"file": "fabric-base.mjs",
|
|
515
|
-
"layer": "L3",
|
|
516
|
-
"imports": [],
|
|
517
|
-
"sha256": "17a92f5e9b71a855648e39e06388bad7f1b969605bd7b1f534ddf67b41a2fb5d"
|
|
518
|
-
},
|
|
519
|
-
{
|
|
520
|
-
"module": "fabric-platform",
|
|
521
|
-
"file": "fabric-platform.mjs",
|
|
522
|
-
"layer": "L3",
|
|
523
|
-
"imports": [
|
|
524
|
-
"fabric-base"
|
|
525
|
-
],
|
|
526
|
-
"sha256": "1349e3638c21caf7da7937ef6a5dfeefe05a8ee733520f0d581624095efeb388"
|
|
527
|
-
},
|
|
528
|
-
{
|
|
529
|
-
"module": "fabric-paths",
|
|
530
|
-
"file": "fabric-paths.mjs",
|
|
531
|
-
"layer": "L3",
|
|
532
|
-
"imports": [
|
|
533
|
-
"fabric-base",
|
|
534
|
-
"fabric-platform"
|
|
535
|
-
],
|
|
536
|
-
"sha256": "e6f5e2ce7c8e7a1452d6ee69977489f4c09ca6f1d3100df9c303274f0b7b16b1"
|
|
537
|
-
},
|
|
538
540
|
{
|
|
539
541
|
"module": "fabric-protocols",
|
|
540
542
|
"file": "fabric-protocols.mjs",
|
|
@@ -542,7 +544,7 @@
|
|
|
542
544
|
"imports": [
|
|
543
545
|
"fabric-secrets"
|
|
544
546
|
],
|
|
545
|
-
"sha256": "
|
|
547
|
+
"sha256": "5d0c222cd7cabebdbfe9a8ae395462b2bba2af7097de1d24511ddf913ac8fdc6"
|
|
546
548
|
},
|
|
547
549
|
{
|
|
548
550
|
"module": "fabric-connections",
|
|
@@ -602,7 +604,7 @@
|
|
|
602
604
|
"fabric-secrets",
|
|
603
605
|
"fabric-usage"
|
|
604
606
|
],
|
|
605
|
-
"sha256": "
|
|
607
|
+
"sha256": "82ab706b9f2322544bb565c78e2077a5503556614161a2a3083d2200bc9e6d69"
|
|
606
608
|
},
|
|
607
609
|
{
|
|
608
610
|
"module": "fabric-auth",
|
|
@@ -722,7 +724,7 @@
|
|
|
722
724
|
"imports": [
|
|
723
725
|
"fabric-identifiers"
|
|
724
726
|
],
|
|
725
|
-
"sha256": "
|
|
727
|
+
"sha256": "c1db7b7bd0d58d82bb6d8dfbc3cd1547a256a333052d367e82ff1b3edf2804d7"
|
|
726
728
|
},
|
|
727
729
|
{
|
|
728
730
|
"module": "fabric-board-link",
|
|
@@ -745,7 +747,7 @@
|
|
|
745
747
|
"fabric-hub",
|
|
746
748
|
"fabric-service"
|
|
747
749
|
],
|
|
748
|
-
"sha256": "
|
|
750
|
+
"sha256": "e9eefb5d34dc66f6d6b528a9c9e85960fd884e6ea5e179c26cbfe3c054ccf7bc"
|
|
749
751
|
},
|
|
750
752
|
{
|
|
751
753
|
"module": "fabric-board-fixture",
|
|
@@ -2037,10 +2039,162 @@
|
|
|
2037
2039
|
"fabric-openrouter.mjs": "f8f0168691f968b7cd85f36aa98e2167e88cc44f1104ff514fd0c7699b339253",
|
|
2038
2040
|
"fabric-package.schema.json": "2ba799f576fad0f608029223c4ccccd122152f1c5dbfa8ce8b31cd63ac92ad44",
|
|
2039
2041
|
"share-registration.schema.json": "0df979d5973809d194723b23a0d18e520d9f1badc0f4a9e557aa33cbe7bc2922"
|
|
2042
|
+
},
|
|
2043
|
+
"0.44.2": {
|
|
2044
|
+
"fabric_jsvalue.py": "0cd4eab0a5d6ae35d097f7c59a08dc29173cb61c561c49e5291a8dad15d36779",
|
|
2045
|
+
"fabric_time.py": "588f383da4ac6a243ea95b6ffc3a0aa99ca94245732dc4937734f190b7af4ae9",
|
|
2046
|
+
"fabric_identifiers.py": "0fd814d521ac3aa39907458265870753046a73f48af3d8581ab864b93b211607",
|
|
2047
|
+
"fabric_secrets.py": "68a0b5e9e90c468ec9ac67b2f0fd1848e08813d6ec1ec14a2a47337eb1a98911",
|
|
2048
|
+
"fabric_crypto.py": "9c34aee20dbe4d6742e4fdbaab68ceb934bbe7dbd3a904c0010824ace16cdeaa",
|
|
2049
|
+
"fabric_base.py": "f62bcc2ed9912660fa875d27a09f60867260cc4925f79873501fd9620be59611",
|
|
2050
|
+
"fabric_platform.py": "a9350dff55ef0fb3a23cdb4d0320a15868b15a8deb10d2eb74d72c58740c284b",
|
|
2051
|
+
"fabric_paths.py": "6c92af34292baddf7e10d3134d0a5b0bb23387741812a9f79c409cf1628bad23",
|
|
2052
|
+
"fabric_estate.py": "50cc12166a00b680ba5b2e458200912d7bcfbef70bd73ec4edf57c7fcfa9b687",
|
|
2053
|
+
"fabric_delegation.py": "4eb5004188fdc6f5c0fd21fb0f9f1f538899a0383bcde0365dea080ef8347182",
|
|
2054
|
+
"fabric_share.py": "78506fe1a60829c525dbf6266a0aa0749a2164290ed94da8249a20b4e9be5605",
|
|
2055
|
+
"fabric_ceremonies.py": "a59e83cf4adb2669a9b98008e3d3a0cba991a35cbff97bc604fc82fe81cfd49f",
|
|
2056
|
+
"fabric_package_schema.py": "e623f0408d38e3343ed66222fb812907c6c52e1a286eb1c1176ab2e64640c9ad",
|
|
2057
|
+
"fabric_package.py": "ff533f1b3f92b4ea0f532fcec50b68c610d47549930eef8ad5247692a64dfb3c",
|
|
2058
|
+
"fabric_protocols.py": "71482284e57334b2d364a44596fc4183baddfe61a80083d3099b7ef423dc6f38",
|
|
2059
|
+
"fabric_connections.py": "77d3ccf863c70e9209d21ef45c46a6db9c06237019bc20d54f8d3946873f3f11",
|
|
2060
|
+
"fabric_lock.py": "ba2399d2137c7a7791b7133b9db9cca36693f4eb7e30955b25a75ade814e95ba",
|
|
2061
|
+
"fabric_usage.py": "ce685cb9fdfd62ea75fff8b1b2be12a2ba758da783e4bfb4dcebe47bcbeb832b",
|
|
2062
|
+
"fabric_backups.py": "02dc5eb66ec956723d3ddba07b6dd15f6a9726d901f4d60edfd02eee57880ceb",
|
|
2063
|
+
"fabric_descriptor.py": "5f6c8f3593fe0cef92d866109cd9def807f67dd5beae2c4bca05452f50521080",
|
|
2064
|
+
"fabric_auth.py": "55794587750f6c9f40935b74295d83d7096cb4b26a0b36ac292334cd87d8f853",
|
|
2065
|
+
"fabric_events.py": "0086886c2c29dbd5c9d152be9d375c5bdf4a29f89b8095baff8490c2bcd64e47",
|
|
2066
|
+
"fabric_logs.py": "86dc55bfafa2a57264722e2403510a249b95de0e4a722b2e4bc3948e3bd93da9",
|
|
2067
|
+
"fabric_supervisors.py": "a2dbf15aa1c4eb9de42996b413103fa4814afd2e4e66d1ab7315f30e06ab6841",
|
|
2068
|
+
"fabric_service.py": "d411433ce6ff3e81189b10b2c1a8462335a97cd99574ab0ee7d1c28cf48e1694",
|
|
2069
|
+
"fabric_profiles.py": "26e21ec29c016000f8ca8053b7b489184854a73be1b7fdc0a18d12990203db9b",
|
|
2070
|
+
"fabric_interop_rules.py": "845d87f7ec601bc2a8ce1ab0dcdc48a95f474ec38ba0ebd7aace85046c3c43f5",
|
|
2071
|
+
"fabric_interop.py": "0b4ca623caad90814426f00e328a7cf2bb52b936d824972136372dd9a0f87d7b",
|
|
2072
|
+
"fabric_hub.py": "b9ac852e601b1d54cf61351677a628afc69faeed7d1fc74ebe541c1cf38e0c2a",
|
|
2073
|
+
"fabric_board_shapes.py": "a8daefdc9283219206875b5d964b49552b6b3ba7e69c925abe08a44afc91c234",
|
|
2074
|
+
"fabric_board_link.py": "b5bff994cb615c6a4bb0d88d020e3a59504166180e1fa1aea3be93224f2aeccb",
|
|
2075
|
+
"fabric_board_session.py": "878ceed970a84087a320fd8eb971c210613a0fa2c524b68793fb32042910581e",
|
|
2076
|
+
"fabric_board_fixture.py": "69761ce205ec640762ec9b591c6903e5a87f844e8d423b041681924027e39d1e",
|
|
2077
|
+
"fabric_board.py": "0f075894b3e352194fcaf3fc7d08dee4e9f1c215e859769ed85fa5010e4a1599",
|
|
2078
|
+
"fabric_http.py": "5d7f72af3a73fdbe8c1f487ecf60cef23a7c46289eba542b03aff4706b8218d4",
|
|
2079
|
+
"fabric_openrouter.py": "2017d898c17001d7275f58267de653be7ecf6acd17ad8d9b24ecb7a43e5617d4",
|
|
2080
|
+
"fabric-jsvalue.mjs": "dfbdb8c41584972c9389750a41719374a1cfc5652ed438dd1623025190b0106e",
|
|
2081
|
+
"fabric-time.mjs": "3ff932069038a720df1c68c6492976906737b2e67e5c12d9c81c418597f661de",
|
|
2082
|
+
"fabric-identifiers.mjs": "a18c2a501a4aa170bfd3d99e571ad6b7662649b4d3b9d2a540c002ea42811bbf",
|
|
2083
|
+
"fabric-secrets.mjs": "6ad8ab18ac899ecc2384e8ec6a3fb689b92be3b9a5ce3a59b92a37d52da5d766",
|
|
2084
|
+
"fabric-crypto.mjs": "038e03689701e3c9721a1e7f8e0a4d02a52d6a5d1661b0dc84035edc3ebbfcf6",
|
|
2085
|
+
"fabric-base.mjs": "7804b2df7715dbbf9702a9b61b6b8cef2110f9a52b04cabd8fb0a66458d87512",
|
|
2086
|
+
"fabric-platform.mjs": "a8119d95ebba4d589a9e401f5d6fc8dda62d59d44e4c1ff811d97fac3771ac0c",
|
|
2087
|
+
"fabric-paths.mjs": "2201b4ed7126f260931b63e8386377b4317d8dcad419d109bf22c683e44b7f29",
|
|
2088
|
+
"fabric-estate.mjs": "912b1ceab57ed20f946986bf14ae2faf41fb8ea539e818164496874f3749ef65",
|
|
2089
|
+
"fabric-delegation.mjs": "85a7e00e606244e7e02f9cbecc3e421bfcb9c1e12cd2a91daadf8a9c2403104d",
|
|
2090
|
+
"fabric-share.mjs": "d40a7405d7bd4c3213ed691330b7549afe8e023db0753b582e249714e672010d",
|
|
2091
|
+
"fabric-ceremonies.mjs": "117d4374c9e95c930a38de7adbd4323774798f4fe6ec6f24afcd6f2c7298ca44",
|
|
2092
|
+
"fabric-package-schema.mjs": "cd28092375db0fc21ffab1f0bb7794f7f8979ee08c64d3b9faf4b3845357caa6",
|
|
2093
|
+
"fabric-package.mjs": "49b757eefcc50e4c91585d5a5694bf3c83d0b03d112c1837f1c9f01466797ab5",
|
|
2094
|
+
"fabric-protocols.mjs": "0ecc3c19bb0bd0393ff3a9ec503034e0ab251eaaf0254edf353e15d1b561f761",
|
|
2095
|
+
"fabric-connections.mjs": "303432e547ce563e90ca9ffcd827f5612f51d3582929834e1add0fdaf6485dcc",
|
|
2096
|
+
"fabric-lock.mjs": "ac219ab0a326d5c43c7c4c255e0c3843d4794de795a60e3af661e7d5350ea052",
|
|
2097
|
+
"fabric-usage.mjs": "e413569620bbc8221bc59e24b27e22d1483825ed18457801ed58d54a57de8114",
|
|
2098
|
+
"fabric-backups.mjs": "849acdc6eba0fff648c8158e61f6b68cccd7bedf0880f7d5ec03a6a20f1e7005",
|
|
2099
|
+
"fabric-descriptor.mjs": "e75b16bbf15ee72a3c581df8164533ea84270f6167e7a0d2527e15bf4b78457d",
|
|
2100
|
+
"fabric-auth.mjs": "3ea6796470fcd829bc72a772fb7e4c37532a09d1e37ff41592dcf1a1a3074ca2",
|
|
2101
|
+
"fabric-events.mjs": "c463d6ffcae24229a5c608d8fcea4268d2ccc5024b19fa10e5a452284068fa71",
|
|
2102
|
+
"fabric-logs.mjs": "58467e5719c16e099d05bbedec47a95712506ab03c33f3cd4be1252e8498a946",
|
|
2103
|
+
"fabric-supervisors.mjs": "9d61c1a17538a5e2453e33e5ae347337336748041bc054478a96dd51f3d4fc51",
|
|
2104
|
+
"fabric-service.mjs": "bc67550e52aa6aa9c6d2ed6cbae52418a3e836623e17164166699f953d8aafa8",
|
|
2105
|
+
"fabric-profiles.mjs": "314376cf2deb87f235fb18b11d3b532e211f585b9af0a9302b5f4cc39971b532",
|
|
2106
|
+
"fabric-interop-rules.mjs": "317f29e407d30ab2afa9bc5e87b3c57c547f216a4c51844d6427d05d6f8f6c9e",
|
|
2107
|
+
"fabric-interop.mjs": "11051f914f2457fd1b3424d7b4174d64500a08f7ce66ac10ed8eda71565511b1",
|
|
2108
|
+
"fabric-hub.mjs": "c005115a864cfd67daa4862097bb14acfe5a60bf653897e5bf8a570dd80f1070",
|
|
2109
|
+
"fabric-board-shapes.mjs": "ad1094397540862b104d9317d6902031d35e64b16c12bf849fb883e12cb78d45",
|
|
2110
|
+
"fabric-board-link.mjs": "4cd6d4e21713a38c8e56f7d59db3148638b8c27c08e774d96a0f6283c6049e0a",
|
|
2111
|
+
"fabric-board-session.mjs": "744a8c9a518c27f2ddfd20b1b22afebc3ccc4f59aeeb7a38d7c12c2ddcae158d",
|
|
2112
|
+
"fabric-board-fixture.mjs": "83c4b7e33ee47b68385faf2569d38d5c8a0c5cb0f8656090f41e1b0eed2f436e",
|
|
2113
|
+
"fabric-board.mjs": "9e7bfe4d412521982224ef12bebfc2ff255eeeaf8d96cf40234ac18de68e7a59",
|
|
2114
|
+
"fabric-http.mjs": "f886bcb49c4353d039387ac9568738dda26697a94dd07fc6a6204500f0bc27bf",
|
|
2115
|
+
"fabric-openrouter.mjs": "f8f0168691f968b7cd85f36aa98e2167e88cc44f1104ff514fd0c7699b339253",
|
|
2116
|
+
"fabric-package.schema.json": "2ba799f576fad0f608029223c4ccccd122152f1c5dbfa8ce8b31cd63ac92ad44",
|
|
2117
|
+
"share-registration.schema.json": "0df979d5973809d194723b23a0d18e520d9f1badc0f4a9e557aa33cbe7bc2922"
|
|
2118
|
+
},
|
|
2119
|
+
"0.45.0": {
|
|
2120
|
+
"fabric_jsvalue.py": "0cd4eab0a5d6ae35d097f7c59a08dc29173cb61c561c49e5291a8dad15d36779",
|
|
2121
|
+
"fabric_time.py": "588f383da4ac6a243ea95b6ffc3a0aa99ca94245732dc4937734f190b7af4ae9",
|
|
2122
|
+
"fabric_identifiers.py": "0fd814d521ac3aa39907458265870753046a73f48af3d8581ab864b93b211607",
|
|
2123
|
+
"fabric_secrets.py": "68a0b5e9e90c468ec9ac67b2f0fd1848e08813d6ec1ec14a2a47337eb1a98911",
|
|
2124
|
+
"fabric_crypto.py": "9c34aee20dbe4d6742e4fdbaab68ceb934bbe7dbd3a904c0010824ace16cdeaa",
|
|
2125
|
+
"fabric_base.py": "f62bcc2ed9912660fa875d27a09f60867260cc4925f79873501fd9620be59611",
|
|
2126
|
+
"fabric_platform.py": "a9350dff55ef0fb3a23cdb4d0320a15868b15a8deb10d2eb74d72c58740c284b",
|
|
2127
|
+
"fabric_paths.py": "6c92af34292baddf7e10d3134d0a5b0bb23387741812a9f79c409cf1628bad23",
|
|
2128
|
+
"fabric_estate.py": "50cc12166a00b680ba5b2e458200912d7bcfbef70bd73ec4edf57c7fcfa9b687",
|
|
2129
|
+
"fabric_delegation.py": "4eb5004188fdc6f5c0fd21fb0f9f1f538899a0383bcde0365dea080ef8347182",
|
|
2130
|
+
"fabric_share.py": "78506fe1a60829c525dbf6266a0aa0749a2164290ed94da8249a20b4e9be5605",
|
|
2131
|
+
"fabric_ceremonies.py": "a59e83cf4adb2669a9b98008e3d3a0cba991a35cbff97bc604fc82fe81cfd49f",
|
|
2132
|
+
"fabric_package_schema.py": "e623f0408d38e3343ed66222fb812907c6c52e1a286eb1c1176ab2e64640c9ad",
|
|
2133
|
+
"fabric_package.py": "ff533f1b3f92b4ea0f532fcec50b68c610d47549930eef8ad5247692a64dfb3c",
|
|
2134
|
+
"fabric_protocols.py": "0d58251ce5f36c8f6372f8e38719543166833399078f824804430b2e070b11f6",
|
|
2135
|
+
"fabric_connections.py": "77d3ccf863c70e9209d21ef45c46a6db9c06237019bc20d54f8d3946873f3f11",
|
|
2136
|
+
"fabric_lock.py": "ba2399d2137c7a7791b7133b9db9cca36693f4eb7e30955b25a75ade814e95ba",
|
|
2137
|
+
"fabric_usage.py": "ce685cb9fdfd62ea75fff8b1b2be12a2ba758da783e4bfb4dcebe47bcbeb832b",
|
|
2138
|
+
"fabric_backups.py": "02dc5eb66ec956723d3ddba07b6dd15f6a9726d901f4d60edfd02eee57880ceb",
|
|
2139
|
+
"fabric_descriptor.py": "64acadc3bbf6e1f95ff275344a7a1fa8b53809e725cd3305a0832a968e7403e9",
|
|
2140
|
+
"fabric_auth.py": "55794587750f6c9f40935b74295d83d7096cb4b26a0b36ac292334cd87d8f853",
|
|
2141
|
+
"fabric_events.py": "0086886c2c29dbd5c9d152be9d375c5bdf4a29f89b8095baff8490c2bcd64e47",
|
|
2142
|
+
"fabric_logs.py": "86dc55bfafa2a57264722e2403510a249b95de0e4a722b2e4bc3948e3bd93da9",
|
|
2143
|
+
"fabric_supervisors.py": "a2dbf15aa1c4eb9de42996b413103fa4814afd2e4e66d1ab7315f30e06ab6841",
|
|
2144
|
+
"fabric_service.py": "d411433ce6ff3e81189b10b2c1a8462335a97cd99574ab0ee7d1c28cf48e1694",
|
|
2145
|
+
"fabric_profiles.py": "26e21ec29c016000f8ca8053b7b489184854a73be1b7fdc0a18d12990203db9b",
|
|
2146
|
+
"fabric_interop_rules.py": "845d87f7ec601bc2a8ce1ab0dcdc48a95f474ec38ba0ebd7aace85046c3c43f5",
|
|
2147
|
+
"fabric_interop.py": "0b4ca623caad90814426f00e328a7cf2bb52b936d824972136372dd9a0f87d7b",
|
|
2148
|
+
"fabric_hub.py": "b9ac852e601b1d54cf61351677a628afc69faeed7d1fc74ebe541c1cf38e0c2a",
|
|
2149
|
+
"fabric_board_shapes.py": "0a0e8d3d40e33dfd8c457aedb85330b2ff25f8c49a33eb6cbd5a5cc8a5007f7e",
|
|
2150
|
+
"fabric_board_link.py": "b5bff994cb615c6a4bb0d88d020e3a59504166180e1fa1aea3be93224f2aeccb",
|
|
2151
|
+
"fabric_board_session.py": "2271834c36c23f6bfa50395cd147e6af99f294ef09325fd15f0759ca8e18d941",
|
|
2152
|
+
"fabric_board_fixture.py": "69761ce205ec640762ec9b591c6903e5a87f844e8d423b041681924027e39d1e",
|
|
2153
|
+
"fabric_board.py": "0f075894b3e352194fcaf3fc7d08dee4e9f1c215e859769ed85fa5010e4a1599",
|
|
2154
|
+
"fabric_http.py": "5d7f72af3a73fdbe8c1f487ecf60cef23a7c46289eba542b03aff4706b8218d4",
|
|
2155
|
+
"fabric_openrouter.py": "2017d898c17001d7275f58267de653be7ecf6acd17ad8d9b24ecb7a43e5617d4",
|
|
2156
|
+
"fabric-jsvalue.mjs": "dfbdb8c41584972c9389750a41719374a1cfc5652ed438dd1623025190b0106e",
|
|
2157
|
+
"fabric-time.mjs": "3ff932069038a720df1c68c6492976906737b2e67e5c12d9c81c418597f661de",
|
|
2158
|
+
"fabric-identifiers.mjs": "a18c2a501a4aa170bfd3d99e571ad6b7662649b4d3b9d2a540c002ea42811bbf",
|
|
2159
|
+
"fabric-secrets.mjs": "6ad8ab18ac899ecc2384e8ec6a3fb689b92be3b9a5ce3a59b92a37d52da5d766",
|
|
2160
|
+
"fabric-crypto.mjs": "038e03689701e3c9721a1e7f8e0a4d02a52d6a5d1661b0dc84035edc3ebbfcf6",
|
|
2161
|
+
"fabric-base.mjs": "7804b2df7715dbbf9702a9b61b6b8cef2110f9a52b04cabd8fb0a66458d87512",
|
|
2162
|
+
"fabric-platform.mjs": "a8119d95ebba4d589a9e401f5d6fc8dda62d59d44e4c1ff811d97fac3771ac0c",
|
|
2163
|
+
"fabric-paths.mjs": "2201b4ed7126f260931b63e8386377b4317d8dcad419d109bf22c683e44b7f29",
|
|
2164
|
+
"fabric-estate.mjs": "912b1ceab57ed20f946986bf14ae2faf41fb8ea539e818164496874f3749ef65",
|
|
2165
|
+
"fabric-delegation.mjs": "85a7e00e606244e7e02f9cbecc3e421bfcb9c1e12cd2a91daadf8a9c2403104d",
|
|
2166
|
+
"fabric-share.mjs": "d40a7405d7bd4c3213ed691330b7549afe8e023db0753b582e249714e672010d",
|
|
2167
|
+
"fabric-ceremonies.mjs": "117d4374c9e95c930a38de7adbd4323774798f4fe6ec6f24afcd6f2c7298ca44",
|
|
2168
|
+
"fabric-package-schema.mjs": "cd28092375db0fc21ffab1f0bb7794f7f8979ee08c64d3b9faf4b3845357caa6",
|
|
2169
|
+
"fabric-package.mjs": "49b757eefcc50e4c91585d5a5694bf3c83d0b03d112c1837f1c9f01466797ab5",
|
|
2170
|
+
"fabric-protocols.mjs": "5d0c222cd7cabebdbfe9a8ae395462b2bba2af7097de1d24511ddf913ac8fdc6",
|
|
2171
|
+
"fabric-connections.mjs": "303432e547ce563e90ca9ffcd827f5612f51d3582929834e1add0fdaf6485dcc",
|
|
2172
|
+
"fabric-lock.mjs": "ac219ab0a326d5c43c7c4c255e0c3843d4794de795a60e3af661e7d5350ea052",
|
|
2173
|
+
"fabric-usage.mjs": "e413569620bbc8221bc59e24b27e22d1483825ed18457801ed58d54a57de8114",
|
|
2174
|
+
"fabric-backups.mjs": "849acdc6eba0fff648c8158e61f6b68cccd7bedf0880f7d5ec03a6a20f1e7005",
|
|
2175
|
+
"fabric-descriptor.mjs": "82ab706b9f2322544bb565c78e2077a5503556614161a2a3083d2200bc9e6d69",
|
|
2176
|
+
"fabric-auth.mjs": "3ea6796470fcd829bc72a772fb7e4c37532a09d1e37ff41592dcf1a1a3074ca2",
|
|
2177
|
+
"fabric-events.mjs": "c463d6ffcae24229a5c608d8fcea4268d2ccc5024b19fa10e5a452284068fa71",
|
|
2178
|
+
"fabric-logs.mjs": "58467e5719c16e099d05bbedec47a95712506ab03c33f3cd4be1252e8498a946",
|
|
2179
|
+
"fabric-supervisors.mjs": "9d61c1a17538a5e2453e33e5ae347337336748041bc054478a96dd51f3d4fc51",
|
|
2180
|
+
"fabric-service.mjs": "bc67550e52aa6aa9c6d2ed6cbae52418a3e836623e17164166699f953d8aafa8",
|
|
2181
|
+
"fabric-profiles.mjs": "314376cf2deb87f235fb18b11d3b532e211f585b9af0a9302b5f4cc39971b532",
|
|
2182
|
+
"fabric-interop-rules.mjs": "317f29e407d30ab2afa9bc5e87b3c57c547f216a4c51844d6427d05d6f8f6c9e",
|
|
2183
|
+
"fabric-interop.mjs": "11051f914f2457fd1b3424d7b4174d64500a08f7ce66ac10ed8eda71565511b1",
|
|
2184
|
+
"fabric-hub.mjs": "c005115a864cfd67daa4862097bb14acfe5a60bf653897e5bf8a570dd80f1070",
|
|
2185
|
+
"fabric-board-shapes.mjs": "c1db7b7bd0d58d82bb6d8dfbc3cd1547a256a333052d367e82ff1b3edf2804d7",
|
|
2186
|
+
"fabric-board-link.mjs": "4cd6d4e21713a38c8e56f7d59db3148638b8c27c08e774d96a0f6283c6049e0a",
|
|
2187
|
+
"fabric-board-session.mjs": "e9eefb5d34dc66f6d6b528a9c9e85960fd884e6ea5e179c26cbfe3c054ccf7bc",
|
|
2188
|
+
"fabric-board-fixture.mjs": "83c4b7e33ee47b68385faf2569d38d5c8a0c5cb0f8656090f41e1b0eed2f436e",
|
|
2189
|
+
"fabric-board.mjs": "9e7bfe4d412521982224ef12bebfc2ff255eeeaf8d96cf40234ac18de68e7a59",
|
|
2190
|
+
"fabric-http.mjs": "f886bcb49c4353d039387ac9568738dda26697a94dd07fc6a6204500f0bc27bf",
|
|
2191
|
+
"fabric-openrouter.mjs": "f8f0168691f968b7cd85f36aa98e2167e88cc44f1104ff514fd0c7699b339253",
|
|
2192
|
+
"fabric-package.schema.json": "2ba799f576fad0f608029223c4ccccd122152f1c5dbfa8ce8b31cd63ac92ad44",
|
|
2193
|
+
"share-registration.schema.json": "34b3997eeaf936ebc861342a23045634a7c18c19f01d7ed4198310d81989f5b0"
|
|
2040
2194
|
}
|
|
2041
2195
|
},
|
|
2042
2196
|
"data": {
|
|
2043
2197
|
"fabric-package.schema.json": "2ba799f576fad0f608029223c4ccccd122152f1c5dbfa8ce8b31cd63ac92ad44",
|
|
2044
|
-
"share-registration.schema.json": "
|
|
2198
|
+
"share-registration.schema.json": "34b3997eeaf936ebc861342a23045634a7c18c19f01d7ed4198310d81989f5b0"
|
|
2045
2199
|
}
|
|
2046
2200
|
}
|
|
@@ -153,7 +153,7 @@
|
|
|
153
153
|
},
|
|
154
154
|
"refusal": {
|
|
155
155
|
"type": "object",
|
|
156
|
-
"description": "The receiver's refusal of a registration after the request authenticated (devices.md transport steps 0 to 8) and its revision is one it reads: 400 malformed, 403 wrong-organization or unassigned-device, 409 already-withdrawn, agent-mismatch, stale-revision or revision-conflict.",
|
|
156
|
+
"description": "The receiver's refusal of a registration after the request authenticated (devices.md transport steps 0 to 8) and its revision is one it reads: 400 malformed, 403 wrong-organization or unassigned-device, 409 already-withdrawn, agent-mismatch, stale-revision or revision-conflict; 403 purpose-not-collected when the person's acknowledged notice does not name a share registration's purposes (DEC-0100), sent again when the notice changes.",
|
|
157
157
|
"required": [
|
|
158
158
|
"error"
|
|
159
159
|
],
|
|
@@ -173,7 +173,8 @@
|
|
|
173
173
|
"already-withdrawn",
|
|
174
174
|
"agent-mismatch",
|
|
175
175
|
"stale-revision",
|
|
176
|
-
"revision-conflict"
|
|
176
|
+
"revision-conflict",
|
|
177
|
+
"purpose-not-collected"
|
|
177
178
|
]
|
|
178
179
|
},
|
|
179
180
|
"message": {
|
|
@@ -5,9 +5,9 @@ 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.
|
|
8
|
+
version: "0.45.0"
|
|
9
9
|
contract-version: "0.1.0"
|
|
10
|
-
contract-commit: "
|
|
10
|
+
contract-commit: "e742016dc396aa31e5a13a893489e43f15786c69"
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
# Creating Fabric-compatible agents
|
|
@@ -136,7 +136,7 @@ python3 <plugin-dir>/skills/adapting-projects-to-fabric/scripts/adapt_project.py
|
|
|
136
136
|
The effect class is declared, never defaulted: ask the author what the agent does outside itself when the request
|
|
137
137
|
does not say. Cost presets are only for a run whose cost varies; their amounts come from the author or measured runs.
|
|
138
138
|
|
|
139
|
-
Pin exactly contract `0.1.0` at commit `
|
|
139
|
+
Pin exactly contract `0.1.0` at commit `e742016dc396aa31e5a13a893489e43f15786c69` and
|
|
140
140
|
read the pinned guide before implementing protocol details. If this skill is installed
|
|
141
141
|
without its sibling, the scaffolder is absent: create the bundle by hand from the pinned
|
|
142
142
|
contract's `docs/guides/connecting-compatible-agents.md` and mark the structural check
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
3
|
"name": "passioncode",
|
|
4
4
|
"displayName": "PassionCode.ai",
|
|
5
|
-
"version": "0.2.
|
|
5
|
+
"version": "0.2.26",
|
|
6
6
|
"description": "Set up and check PassionCode.ai on a computer with one command (setting-up-passioncode), the organisation's working rules for every contributor's agent (working-in-passioncode), and a once-a-day check at session start that keeps the PassionCode.ai skill set current.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "PassionCode.ai",
|