@ainize/core 0.1.3 → 0.1.5

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.
@@ -16,4 +16,60 @@ export declare function teachAuthHeaderFor(key: {
16
16
  privateKey: string;
17
17
  address: string;
18
18
  }, t: TeachAuthTarget, ts?: number): string;
19
+ /** Header that carries the delegation, beside the ordinary `x-ainize-auth`. */
20
+ export declare const DELEGATE_HEADER = "x-ainize-delegate";
21
+ /** The longest a node will honour one delegation, however long the owner wrote. */
22
+ export declare const DELEGATION_MAX_MS: number;
23
+ /**
24
+ * Why delegation exists at all.
25
+ *
26
+ * A teaching key signs EVERY request. That is right for a key the browser holds and wrong for a key a wallet
27
+ * extension holds: `window.ainetwork.signMessage` is a user-facing prompt, so signing per request would put a
28
+ * confirmation dialog in front of every live test, every dataset page and every poll of a running lesson. The
29
+ * alternative people reach for — asking the extension for the private key — does not exist and should not.
30
+ *
31
+ * So the wallet signs ONCE, and what it signs is permission for a freshly generated browser key to act as that
32
+ * address. The browser key signs the requests, exactly as before; the delegation rides alongside and says whose
33
+ * they are.
34
+ *
35
+ * WHAT KEEPS IT HONEST, and each of these is checked in `verifyDelegation`:
36
+ *
37
+ * it names THIS node — a delegation shown to one node cannot be replayed at another.
38
+ * it names THAT key — a stolen delegation is inert without the browser key it authorises, and that key
39
+ * never leaves the browser.
40
+ * it expires — and the node caps the window at `DELEGATION_MAX_MS` no matter what the owner
41
+ * wrote, so one careless prompt cannot authorise a key for ever.
42
+ * the per-request proof is unchanged — the v2 signature still comes from the delegate key, so the replay
43
+ * cache, the route binding and the body binding all still apply.
44
+ *
45
+ * What it is NOT: a login. The node keeps no session, issues nothing, and forgets the delegation the moment the
46
+ * request ends. Two tabs, a CLI and a script can hold different delegate keys for the same owner at once — which
47
+ * is what makes several lessons under one identity possible, rather than a thing to be worked around.
48
+ */
49
+ export declare function delegateMessage(t: {
50
+ node: string;
51
+ delegate: string;
52
+ expires: number;
53
+ }): string;
54
+ export interface Delegation {
55
+ owner: string;
56
+ expires: number;
57
+ signature: string;
58
+ }
59
+ /** Parse `x-ainize-delegate: <owner>:<expires>:<sig>`. Returns null on anything malformed. */
60
+ export declare function parseDelegation(header: string | undefined | null): Delegation | null;
61
+ /** The header an owner's wallet produces once, and every delegated request then carries unchanged. */
62
+ export declare function delegateHeader(d: Delegation): string;
63
+ /**
64
+ * The address a delegated request acts as, or null.
65
+ *
66
+ * `verify` is passed in rather than imported so this stays usable from the browser bundle, which verifies with
67
+ * `@noble/secp256k1` and must not pull `@ainblockchain/ain-util` in.
68
+ */
69
+ export declare function verifyDelegation(header: string | undefined | null, ctx: {
70
+ node: string;
71
+ delegate: string;
72
+ now?: number;
73
+ maxMs?: number;
74
+ }, verify: (message: string, signature: string, address: string) => boolean): string | null;
19
75
  //# sourceMappingURL=teach-auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"teach-auth.d.ts","sourceRoot":"","sources":["../src/teach-auth.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,kBAAkB,QAAa,CAAC;AAC7C,eAAO,MAAM,aAAa,OAAO,CAAC;AAElC,MAAM,WAAW,eAAe;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE;AAIpI,6IAA6I;AAC7I,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,eAAe,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAI5E;AAED,0FAA0F;AAC1F,wBAAgB,kBAAkB,CAAC,GAAG,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,EAAE,eAAe,EAAE,EAAE,SAAa,GAAG,MAAM,CAE5H"}
1
+ {"version":3,"file":"teach-auth.d.ts","sourceRoot":"","sources":["../src/teach-auth.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,kBAAkB,QAAa,CAAC;AAC7C,eAAO,MAAM,aAAa,OAAO,CAAC;AAElC,MAAM,WAAW,eAAe;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE;AAIpI,6IAA6I;AAC7I,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,eAAe,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAI5E;AAED,0FAA0F;AAC1F,wBAAgB,kBAAkB,CAAC,GAAG,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,EAAE,eAAe,EAAE,EAAE,SAAa,GAAG,MAAM,CAE5H;AAID,+EAA+E;AAC/E,eAAO,MAAM,eAAe,sBAAsB,CAAC;AACnD,mFAAmF;AACnF,eAAO,MAAM,iBAAiB,QAAmB,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAE9F;AAED,MAAM,WAAW,UAAU;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AAEjF,8FAA8F;AAC9F,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,UAAU,GAAG,IAAI,CAQpF;AAED,sGAAsG;AACtG,wBAAgB,cAAc,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAEpD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EACjC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EACrE,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,GACvE,MAAM,GAAG,IAAI,CASf"}
@@ -30,4 +30,75 @@ export function teachAuthMessage(t) {
30
30
  export function teachAuthHeaderFor(key, t, ts = Date.now()) {
31
31
  return `${key.address}:${ts}:${signMessage(teachAuthMessage({ ...t, ts }), key.privateKey)}:${TEACH_AUTH_V2}`;
32
32
  }
33
+ // ------------------------------------------------------------------ delegation (AIN Wallet sign-in)
34
+ /** Header that carries the delegation, beside the ordinary `x-ainize-auth`. */
35
+ export const DELEGATE_HEADER = 'x-ainize-delegate';
36
+ /** The longest a node will honour one delegation, however long the owner wrote. */
37
+ export const DELEGATION_MAX_MS = 24 * 60 * 60_000;
38
+ /**
39
+ * Why delegation exists at all.
40
+ *
41
+ * A teaching key signs EVERY request. That is right for a key the browser holds and wrong for a key a wallet
42
+ * extension holds: `window.ainetwork.signMessage` is a user-facing prompt, so signing per request would put a
43
+ * confirmation dialog in front of every live test, every dataset page and every poll of a running lesson. The
44
+ * alternative people reach for — asking the extension for the private key — does not exist and should not.
45
+ *
46
+ * So the wallet signs ONCE, and what it signs is permission for a freshly generated browser key to act as that
47
+ * address. The browser key signs the requests, exactly as before; the delegation rides alongside and says whose
48
+ * they are.
49
+ *
50
+ * WHAT KEEPS IT HONEST, and each of these is checked in `verifyDelegation`:
51
+ *
52
+ * it names THIS node — a delegation shown to one node cannot be replayed at another.
53
+ * it names THAT key — a stolen delegation is inert without the browser key it authorises, and that key
54
+ * never leaves the browser.
55
+ * it expires — and the node caps the window at `DELEGATION_MAX_MS` no matter what the owner
56
+ * wrote, so one careless prompt cannot authorise a key for ever.
57
+ * the per-request proof is unchanged — the v2 signature still comes from the delegate key, so the replay
58
+ * cache, the route binding and the body binding all still apply.
59
+ *
60
+ * What it is NOT: a login. The node keeps no session, issues nothing, and forgets the delegation the moment the
61
+ * request ends. Two tabs, a CLI and a script can hold different delegate keys for the same owner at once — which
62
+ * is what makes several lessons under one identity possible, rather than a thing to be worked around.
63
+ */
64
+ export function delegateMessage(t) {
65
+ return ['delegate', t.node, t.delegate.toLowerCase(), String(t.expires)].join(':');
66
+ }
67
+ /** Parse `x-ainize-delegate: <owner>:<expires>:<sig>`. Returns null on anything malformed. */
68
+ export function parseDelegation(header) {
69
+ if (!header)
70
+ return null;
71
+ const parts = header.split(':');
72
+ if (parts.length !== 3)
73
+ return null;
74
+ const [owner, expStr, signature] = parts;
75
+ const expires = Number(expStr);
76
+ if (!/^0x[0-9a-fA-F]{40}$/.test(owner ?? '') || !Number.isFinite(expires) || !signature)
77
+ return null;
78
+ return { owner, expires, signature };
79
+ }
80
+ /** The header an owner's wallet produces once, and every delegated request then carries unchanged. */
81
+ export function delegateHeader(d) {
82
+ return `${d.owner}:${d.expires}:${d.signature}`;
83
+ }
84
+ /**
85
+ * The address a delegated request acts as, or null.
86
+ *
87
+ * `verify` is passed in rather than imported so this stays usable from the browser bundle, which verifies with
88
+ * `@noble/secp256k1` and must not pull `@ainblockchain/ain-util` in.
89
+ */
90
+ export function verifyDelegation(header, ctx, verify) {
91
+ const d = parseDelegation(header);
92
+ if (!d)
93
+ return null;
94
+ const now = ctx.now ?? Date.now();
95
+ if (d.expires <= now)
96
+ return null;
97
+ if (d.expires - now > (ctx.maxMs ?? DELEGATION_MAX_MS))
98
+ return null;
99
+ if (d.owner.toLowerCase() === ctx.delegate.toLowerCase())
100
+ return null; // a key delegating to itself proves nothing
101
+ const message = delegateMessage({ node: ctx.node, delegate: ctx.delegate, expires: d.expires });
102
+ return verify(message, d.signature, d.owner) ? d.owner : null;
103
+ }
33
104
  //# sourceMappingURL=teach-auth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"teach-auth.js","sourceRoot":"","sources":["../src/teach-auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,GAAG,MAAM,CAAC;AAC7C,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC;AAIlC,MAAM,MAAM,GAAG,CAAC,CAAsB,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAExF,6IAA6I;AAC7I,MAAM,UAAU,gBAAgB,CAAC,CAAmC;IAClE,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3F,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7F,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,kBAAkB,CAAC,GAA4C,EAAE,CAAkB,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE;IAClH,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,EAAE,IAAI,WAAW,CAAC,gBAAgB,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,UAAU,CAAC,IAAI,aAAa,EAAE,CAAC;AAChH,CAAC"}
1
+ {"version":3,"file":"teach-auth.js","sourceRoot":"","sources":["../src/teach-auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,GAAG,MAAM,CAAC;AAC7C,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC;AAIlC,MAAM,MAAM,GAAG,CAAC,CAAsB,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAExF,6IAA6I;AAC7I,MAAM,UAAU,gBAAgB,CAAC,CAAmC;IAClE,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3F,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7F,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,kBAAkB,CAAC,GAA4C,EAAE,CAAkB,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE;IAClH,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,EAAE,IAAI,WAAW,CAAC,gBAAgB,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,UAAU,CAAC,IAAI,aAAa,EAAE,CAAC;AAChH,CAAC;AAED,qGAAqG;AAErG,+EAA+E;AAC/E,MAAM,CAAC,MAAM,eAAe,GAAG,mBAAmB,CAAC;AACnD,mFAAmF;AACnF,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,eAAe,CAAC,CAAsD;IACpF,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACrF,CAAC;AAID,8FAA8F;AAC9F,MAAM,UAAU,eAAe,CAAC,MAAiC;IAC/D,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC;IACzC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IACrG,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AACvC,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,cAAc,CAAC,CAAa;IAC1C,OAAO,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;AAClD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAiC,EACjC,GAAqE,EACrE,MAAwE;IAExE,MAAM,CAAC,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IAClC,IAAI,CAAC,CAAC,OAAO,IAAI,GAAG;QAAE,OAAO,IAAI,CAAC;IAClC,IAAI,CAAC,CAAC,OAAO,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,iBAAiB,CAAC;QAAE,OAAO,IAAI,CAAC;IACpE,IAAI,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE;QAAE,OAAO,IAAI,CAAC,CAAG,4CAA4C;IACrH,MAAM,OAAO,GAAG,eAAe,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAChG,OAAO,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAChE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ainize/core",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Ainize core \u2014 knowledge-patch schemas, lineage, verification and ledger (AIN) bindings shared by @ainize/node and @ainize/cli",
5
5
  "license": "MIT",
6
6
  "repository": {