@nomosprotocol/sdk 1.4.0 → 2.3.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/README.md +98 -1
- package/dist/index.cjs +6217 -32
- package/dist/index.d.cts +751 -18
- package/dist/index.d.ts +751 -18
- package/dist/index.js +6169 -30
- package/package.json +25 -9
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -14,6 +14,103 @@ Give `can()` an authority, an action, and the relevant facts. NOMOS verifies the
|
|
|
14
14
|
npm install @nomosprotocol/sdk
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
## Acts: your first verified, committed change in five minutes
|
|
18
|
+
|
|
19
|
+
An **Act** carries an exact change together with its proof: the sealed rules it acts under, facts
|
|
20
|
+
signed by the systems that know them, and the approvals of the people who must approve. The system
|
|
21
|
+
that makes the change verifies all of it itself, locally, and commits exactly that change or
|
|
22
|
+
nothing (NOMOS-SPEC-008, NOMOS-SPEC-009).
|
|
23
|
+
|
|
24
|
+
**1. Start a complete local world.** It includes a shop, a purchasing policy, a finance system that
|
|
25
|
+
states budgets, and a manager who approves. Every key is a labelled test key.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx @nomosprotocol/cli dev
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**2. Act as an agent.** One call discovers the shop, gathers the signed budget from finance,
|
|
32
|
+
submits, and returns the shop's verdict:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { act } from '@nomosprotocol/sdk';
|
|
36
|
+
|
|
37
|
+
const r = await act({
|
|
38
|
+
to: 'http://localhost:4747',
|
|
39
|
+
action: { type: 'purchase', subject: 'DEPT-17', params: { amount: 500, vendor: 'paperco' } },
|
|
40
|
+
});
|
|
41
|
+
console.log(r.status, r.summary); // committed Committed by shop.local.
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Try `amount: 2000`: the manager must approve, and the approval link prints in the sandbox window.
|
|
45
|
+
Try `amount: 9000` (over budget), `vendor: 'shadyco'` (blocked), or `subject: 'DEPT-99'` (finance
|
|
46
|
+
knows nothing). `r.missing` then names exactly the fact that is missing, and why.
|
|
47
|
+
|
|
48
|
+
**3. Be the system that makes the change.** Wrap your existing handler with `accept()`. It runs the
|
|
49
|
+
verifier locally and then, in one transaction, records the nonce, re-reads your own facts, hands
|
|
50
|
+
`commit` exactly the verified action, and stores the receipt:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import pg from 'pg';
|
|
54
|
+
import { accept, postgresStore } from '@nomosprotocol/sdk';
|
|
55
|
+
|
|
56
|
+
const store = postgresStore(new pg.Pool({ connectionString: process.env.DATABASE_URL }));
|
|
57
|
+
await store.migrate(); // once: creates the nomos_acts table
|
|
58
|
+
|
|
59
|
+
const rp = accept({
|
|
60
|
+
relyingPartyId: 'orders.acme.example',
|
|
61
|
+
root: ACME_ROOT_PEM, // the root you pin; there is no default
|
|
62
|
+
actEndpoint: 'https://orders.acme.example/nomos/acts',
|
|
63
|
+
authorities: [{ artifactId: 'acme-purchasing', issuer: 'https://policy.acme.example',
|
|
64
|
+
actions: ['purchase'], currencyPolicy: 'record', inForceSealHash: POLICY_SEAL_HASH }],
|
|
65
|
+
localFacts: async (act) => ({ vendor_blocked: await isBlocked(act.action.params.vendor) }),
|
|
66
|
+
commit: async (action, { tx }) => createOrder(tx, action), // your existing code, on the same transaction
|
|
67
|
+
store, // nonces, receipts and the Acts themselves
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
app.use(rp.express()); // Express, Connect, node:http
|
|
71
|
+
// or: export default { fetch: rp.fetch } — Hono, Next.js, Cloudflare Workers, Deno, Bun
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`accept()` serves your discovery document at `/.well-known/nomos-relying-party`, generated from this
|
|
75
|
+
same configuration, and answers every Act with the status NOMOS-SPEC-009 assigns.
|
|
76
|
+
|
|
77
|
+
`postgresStore()` records the nonce, your change and the receipt in one transaction: `commit`
|
|
78
|
+
receives `tx`, the same client. Under any number of concurrent submissions of one Act exactly one
|
|
79
|
+
commits and the rest get `409` with its receipt, and the exact Act is kept beside its receipt so
|
|
80
|
+
an auditor can re-verify it later. It takes a node-postgres `Pool` or anything with the same
|
|
81
|
+
`query`/`connect` methods (Neon's serverless driver on edge runtimes, for example) and depends on
|
|
82
|
+
no driver itself. `memoryStore()`, the default, is for development only.
|
|
83
|
+
|
|
84
|
+
| Verdict | Status |
|
|
85
|
+
|---|---|
|
|
86
|
+
| AUTHORIZED, committed | 201 |
|
|
87
|
+
| ESCALATED | 202 |
|
|
88
|
+
| INCOMPLETE | 422 |
|
|
89
|
+
| DENIED | 403 |
|
|
90
|
+
| REPLAYED | 409, with the original receipt |
|
|
91
|
+
| any other refusal | 400 |
|
|
92
|
+
|
|
93
|
+
**Certificates and revocations.** `act()` presents exactly the certificates an Act relies on
|
|
94
|
+
(NOMOS-SPEC-009 0.2.0), so an issuer can certify any number of approvers. Witnesses and approvers
|
|
95
|
+
can return their own chains with what they sign (`keyCerts`). On the relying party,
|
|
96
|
+
`revocations: revocationSource({ url, root, maxAgeSeconds })` reads the issuer's signed list
|
|
97
|
+
(NOMOS-SPEC-007 rev. 1.10). Revocations are never forgotten, and without a current list
|
|
98
|
+
`accept()` answers 503 instead of committing.
|
|
99
|
+
|
|
100
|
+
**The other roles** are one call each:
|
|
101
|
+
- `issuer()` publishes your sealed policies and certificates;
|
|
102
|
+
- `witness()` turns an existing lookup into signed statements;
|
|
103
|
+
- `approver()` shows a person the exact change and signs their consent; `passkeyApprover()` has them
|
|
104
|
+
sign it with Face ID, Touch ID or a security key, enrolled through a single-use link
|
|
105
|
+
(`nomos enroll`), so no server can approve for them.
|
|
106
|
+
|
|
107
|
+
Keys are `Signer`s, so they can live in your KMS or HSM: [`@nomosprotocol/signers`](../packages/signers) has adapters for AWS KMS, Google Cloud KMS, Azure Key Vault and any other HSM.
|
|
108
|
+
|
|
109
|
+
**Any MCP agent** can carry Acts with no code: the `nomos-mcp` server has an `act` tool.
|
|
110
|
+
|
|
111
|
+
Verification is `@nomosprotocol/verify`, re-exported here as `verifyAct`, `verifyArtifact` and
|
|
112
|
+
`verifySeal`. It runs entirely offline, in Node, browsers and edge runtimes.
|
|
113
|
+
|
|
17
114
|
## `can()` — one function for authority
|
|
18
115
|
|
|
19
116
|
`can()` is the primary query interface to NOMOS.
|
|
@@ -434,7 +531,7 @@ The long-term goal is simple:
|
|
|
434
531
|
|
|
435
532
|
## Requirements
|
|
436
533
|
|
|
437
|
-
* Node.js
|
|
534
|
+
* Node.js 20+
|
|
438
535
|
* TypeScript supported
|
|
439
536
|
* ESM and CommonJS builds
|
|
440
537
|
* Full TypeScript declarations
|