@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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +264 -0
  3. package/dist/cache.d.ts +10 -0
  4. package/dist/cache.d.ts.map +1 -0
  5. package/dist/cache.js +58 -0
  6. package/dist/cache.js.map +1 -0
  7. package/dist/guard.d.ts +19 -0
  8. package/dist/guard.d.ts.map +1 -0
  9. package/dist/guard.js +57 -0
  10. package/dist/guard.js.map +1 -0
  11. package/dist/index.d.ts +34 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +30 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/install.d.ts +8 -0
  16. package/dist/install.d.ts.map +1 -0
  17. package/dist/install.js +123 -0
  18. package/dist/install.js.map +1 -0
  19. package/dist/poll.d.ts +10 -0
  20. package/dist/poll.d.ts.map +1 -0
  21. package/dist/poll.js +60 -0
  22. package/dist/poll.js.map +1 -0
  23. package/dist/refusal.d.ts +92 -0
  24. package/dist/refusal.d.ts.map +1 -0
  25. package/dist/refusal.js +188 -0
  26. package/dist/refusal.js.map +1 -0
  27. package/dist/registrar.d.ts +77 -0
  28. package/dist/registrar.d.ts.map +1 -0
  29. package/dist/registrar.js +106 -0
  30. package/dist/registrar.js.map +1 -0
  31. package/dist/result.d.ts +16 -0
  32. package/dist/result.d.ts.map +1 -0
  33. package/dist/result.js +12 -0
  34. package/dist/result.js.map +1 -0
  35. package/dist/schedule.d.ts +14 -0
  36. package/dist/schedule.d.ts.map +1 -0
  37. package/dist/schedule.js +20 -0
  38. package/dist/schedule.js.map +1 -0
  39. package/dist/showcase/breaker.d.ts +91 -0
  40. package/dist/showcase/breaker.d.ts.map +1 -0
  41. package/dist/showcase/breaker.js +132 -0
  42. package/dist/showcase/breaker.js.map +1 -0
  43. package/dist/showcase/connect.d.ts +39 -0
  44. package/dist/showcase/connect.d.ts.map +1 -0
  45. package/dist/showcase/connect.js +98 -0
  46. package/dist/showcase/connect.js.map +1 -0
  47. package/dist/showcase/descriptions.d.ts +46 -0
  48. package/dist/showcase/descriptions.d.ts.map +1 -0
  49. package/dist/showcase/descriptions.js +86 -0
  50. package/dist/showcase/descriptions.js.map +1 -0
  51. package/dist/showcase/instructions.d.ts +13 -0
  52. package/dist/showcase/instructions.d.ts.map +1 -0
  53. package/dist/showcase/instructions.js +20 -0
  54. package/dist/showcase/instructions.js.map +1 -0
  55. package/dist/showcase/marked-fetch.d.ts +37 -0
  56. package/dist/showcase/marked-fetch.d.ts.map +1 -0
  57. package/dist/showcase/marked-fetch.js +48 -0
  58. package/dist/showcase/marked-fetch.js.map +1 -0
  59. package/dist/showcase/tools.d.ts +49 -0
  60. package/dist/showcase/tools.d.ts.map +1 -0
  61. package/dist/showcase/tools.js +198 -0
  62. package/dist/showcase/tools.js.map +1 -0
  63. package/dist/types.d.ts +59 -0
  64. package/dist/types.d.ts.map +1 -0
  65. package/dist/types.js +2 -0
  66. package/dist/types.js.map +1 -0
  67. package/dist/verdict.d.ts +47 -0
  68. package/dist/verdict.d.ts.map +1 -0
  69. package/dist/verdict.js +89 -0
  70. package/dist/verdict.js.map +1 -0
  71. package/package.json +69 -0
@@ -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
+ }