@proof-holdings/delegation-self-refusal 0.1.0
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/LICENSE +21 -0
- package/README.md +264 -0
- package/dist/cache.d.ts +10 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +58 -0
- package/dist/cache.js.map +1 -0
- package/dist/guard.d.ts +19 -0
- package/dist/guard.d.ts.map +1 -0
- package/dist/guard.js +57 -0
- package/dist/guard.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/install.d.ts +8 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +123 -0
- package/dist/install.js.map +1 -0
- package/dist/poll.d.ts +10 -0
- package/dist/poll.d.ts.map +1 -0
- package/dist/poll.js +60 -0
- package/dist/poll.js.map +1 -0
- package/dist/refusal.d.ts +92 -0
- package/dist/refusal.d.ts.map +1 -0
- package/dist/refusal.js +188 -0
- package/dist/refusal.js.map +1 -0
- package/dist/registrar.d.ts +77 -0
- package/dist/registrar.d.ts.map +1 -0
- package/dist/registrar.js +106 -0
- package/dist/registrar.js.map +1 -0
- package/dist/result.d.ts +16 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js +12 -0
- package/dist/result.js.map +1 -0
- package/dist/schedule.d.ts +14 -0
- package/dist/schedule.d.ts.map +1 -0
- package/dist/schedule.js +20 -0
- package/dist/schedule.js.map +1 -0
- package/dist/showcase/breaker.d.ts +91 -0
- package/dist/showcase/breaker.d.ts.map +1 -0
- package/dist/showcase/breaker.js +132 -0
- package/dist/showcase/breaker.js.map +1 -0
- package/dist/showcase/connect.d.ts +39 -0
- package/dist/showcase/connect.d.ts.map +1 -0
- package/dist/showcase/connect.js +98 -0
- package/dist/showcase/connect.js.map +1 -0
- package/dist/showcase/descriptions.d.ts +46 -0
- package/dist/showcase/descriptions.d.ts.map +1 -0
- package/dist/showcase/descriptions.js +86 -0
- package/dist/showcase/descriptions.js.map +1 -0
- package/dist/showcase/instructions.d.ts +13 -0
- package/dist/showcase/instructions.d.ts.map +1 -0
- package/dist/showcase/instructions.js +20 -0
- package/dist/showcase/instructions.js.map +1 -0
- package/dist/showcase/marked-fetch.d.ts +37 -0
- package/dist/showcase/marked-fetch.d.ts.map +1 -0
- package/dist/showcase/marked-fetch.js +48 -0
- package/dist/showcase/marked-fetch.js.map +1 -0
- package/dist/showcase/tools.d.ts +49 -0
- package/dist/showcase/tools.d.ts.map +1 -0
- package/dist/showcase/tools.js +198 -0
- package/dist/showcase/tools.js.map +1 -0
- package/dist/types.d.ts +59 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/verdict.d.ts +47 -0
- package/dist/verdict.d.ts.map +1 -0
- package/dist/verdict.js +89 -0
- package/dist/verdict.js.map +1 -0
- package/package.json +69 -0
package/dist/verdict.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { defaultCacheDir, writeCache, readCache } from './cache.js';
|
|
2
|
+
import { DEFAULT_BASE_URL, pollDelegationStatus } from './poll.js';
|
|
3
|
+
import { MAX_GRACE_FAILURES, nextIntervalMs } from './schedule.js';
|
|
4
|
+
/**
|
|
5
|
+
* Applies the documented defaults once. Both `guardDelegation` and `installProofLayer` call this
|
|
6
|
+
* exactly once per installation and hand the SAME object to the gate and to the showcase — two
|
|
7
|
+
* independent resolutions could disagree on `cacheDir` and silently split the grace state machine
|
|
8
|
+
* across two files.
|
|
9
|
+
*/
|
|
10
|
+
export function resolveOptions(opts) {
|
|
11
|
+
return {
|
|
12
|
+
...opts,
|
|
13
|
+
token: opts.token,
|
|
14
|
+
baseUrl: opts.baseUrl ?? DEFAULT_BASE_URL,
|
|
15
|
+
cacheDir: opts.cacheDir ?? defaultCacheDir(),
|
|
16
|
+
pollIntervalMs: opts.pollIntervalMs ?? 60_000,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Caching is an optimization on top of an already-computed verdict, not a precondition for
|
|
21
|
+
* returning it — a filesystem error here (read-only FS, permission denial, disk full) must not
|
|
22
|
+
* throw out of the gated handler and must not discard a verdict that was already determined.
|
|
23
|
+
* `console.error` (never `console.log`/stdout) is this repo's established safe channel for an
|
|
24
|
+
* MCP stdio server, where stdout is the JSON-RPC transport itself (mcp/src/server.ts:96,100).
|
|
25
|
+
*/
|
|
26
|
+
export function safeWriteCache(cacheDir, token, entry) {
|
|
27
|
+
try {
|
|
28
|
+
writeCache(cacheDir, token, entry);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
console.error(`delegation-self-refusal: failed to persist cache entry (continuing with the verdict already computed): ${error instanceof Error ? error.message : String(error)}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Applies the grace-window state machine and returns a definitive verdict. A cold start (no cache
|
|
36
|
+
* file at all) has no grace to extend — an unresolved first poll refuses immediately (SC-12: "a
|
|
37
|
+
* first run has none"). A cached UnresolvedVerdict is never persisted as `lastDecided`: only
|
|
38
|
+
* ValidVerdict/RefusedVerdict are ever served from cache.
|
|
39
|
+
*/
|
|
40
|
+
export async function currentVerdict(opts) {
|
|
41
|
+
const cache = readCache(opts.cacheDir, opts.token);
|
|
42
|
+
const interval = nextIntervalMs(opts.pollIntervalMs);
|
|
43
|
+
const dueForPoll = !cache || Date.now() - cache.lastCheckedAtMs >= interval;
|
|
44
|
+
let result;
|
|
45
|
+
if (dueForPoll) {
|
|
46
|
+
result = await pollDelegationStatus(opts.token, opts.baseUrl, opts.fetchImpl);
|
|
47
|
+
}
|
|
48
|
+
else if (cache?.lastDecided) {
|
|
49
|
+
return cache.lastDecided;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
result = { kind: 'unresolved' };
|
|
53
|
+
}
|
|
54
|
+
if (result.kind !== 'unresolved') {
|
|
55
|
+
safeWriteCache(opts.cacheDir, opts.token, {
|
|
56
|
+
lastDecided: result,
|
|
57
|
+
lastCheckedAtMs: Date.now(),
|
|
58
|
+
consecutiveUnresolved: 0,
|
|
59
|
+
});
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
const failures = (cache?.consecutiveUnresolved ?? 0) + 1;
|
|
63
|
+
if (cache?.lastDecided && failures <= MAX_GRACE_FAILURES) {
|
|
64
|
+
safeWriteCache(opts.cacheDir, opts.token, {
|
|
65
|
+
lastDecided: cache.lastDecided,
|
|
66
|
+
lastCheckedAtMs: Date.now(),
|
|
67
|
+
consecutiveUnresolved: failures,
|
|
68
|
+
});
|
|
69
|
+
return cache.lastDecided;
|
|
70
|
+
}
|
|
71
|
+
const refusal = cache?.lastDecided
|
|
72
|
+
? {
|
|
73
|
+
kind: 'refused',
|
|
74
|
+
reason: 'grace_exhausted',
|
|
75
|
+
message: `Could not reconfirm authorization after ${failures} consecutive failed checks`,
|
|
76
|
+
}
|
|
77
|
+
: {
|
|
78
|
+
kind: 'refused',
|
|
79
|
+
reason: 'unresolved_at_startup',
|
|
80
|
+
message: 'Authorization could not be confirmed on the first check',
|
|
81
|
+
};
|
|
82
|
+
safeWriteCache(opts.cacheDir, opts.token, {
|
|
83
|
+
lastDecided: refusal,
|
|
84
|
+
lastCheckedAtMs: Date.now(),
|
|
85
|
+
consecutiveUnresolved: failures,
|
|
86
|
+
});
|
|
87
|
+
return refusal;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=verdict.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verdict.js","sourceRoot":"","sources":["../src/verdict.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@proof-holdings/delegation-self-refusal",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A delegated MCP server that refuses its own tool calls once its Proof of Delegation is revoked, suspended, or expired — self-enforcement, not consumer verification",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "proof.holdings <hello@proof.holdings> (https://proof.holdings)",
|
|
8
|
+
"homepage": "https://proof.holdings",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/ProofHoldings/delegation-self-refusal.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"email": "hello@proof.holdings",
|
|
15
|
+
"url": "https://proof.holdings/support"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"proof-of-delegation",
|
|
19
|
+
"delegation",
|
|
20
|
+
"revocation",
|
|
21
|
+
"mcp",
|
|
22
|
+
"agent-card",
|
|
23
|
+
"self-enforcement"
|
|
24
|
+
],
|
|
25
|
+
"main": "dist/index.js",
|
|
26
|
+
"types": "dist/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsc",
|
|
35
|
+
"typecheck": "tsc --noEmit",
|
|
36
|
+
"test": "vitest run",
|
|
37
|
+
"test:watch": "vitest",
|
|
38
|
+
"prepublishOnly": "npm run build && npm test"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"zod": "^3.25 || ^4.0"
|
|
42
|
+
},
|
|
43
|
+
"peerDependenciesMeta": {
|
|
44
|
+
"zod": {
|
|
45
|
+
"optional": false
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
50
|
+
"@types/node": "^20.11.0",
|
|
51
|
+
"typescript": "^5.5.0",
|
|
52
|
+
"vitest": "^3.0.0",
|
|
53
|
+
"zod": "^3.25.76"
|
|
54
|
+
},
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=18.0.0"
|
|
57
|
+
},
|
|
58
|
+
"files": [
|
|
59
|
+
"dist",
|
|
60
|
+
"README.md",
|
|
61
|
+
"LICENSE"
|
|
62
|
+
],
|
|
63
|
+
"dependencies": {
|
|
64
|
+
"@proof-holdings/delegation-verifier": "^0.1.0"
|
|
65
|
+
},
|
|
66
|
+
"publishConfig": {
|
|
67
|
+
"access": "public"
|
|
68
|
+
}
|
|
69
|
+
}
|