@tacet-ink/journal-core 0.3.0 → 0.3.2
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 +7 -6
- package/dist/client/argon-auto.d.ts +47 -0
- package/dist/client/argon-auto.js +226 -0
- package/dist/client/argon-worker.d.ts +31 -0
- package/dist/client/argon-worker.js +147 -0
- package/dist/client/argon2.d.ts +17 -5
- package/dist/client/argon2.js +13 -3
- package/dist/client/note-crypto.d.ts +2 -1
- package/dist/client/vault-error.d.ts +44 -0
- package/dist/client/vault-error.js +19 -0
- package/dist/client/vault.d.ts +107 -0
- package/dist/client/vault.js +391 -0
- package/dist/client/vendor/hash-wasm-argon2.d.ts +14 -0
- package/dist/client/vendor/hash-wasm-argon2.js +160 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/server/env.d.ts +6 -0
- package/dist/server/ratelimit.d.ts +14 -0
- package/dist/server/ratelimit.js +54 -1
- package/docs/format-spec.md +5 -5
- package/docs/vectors/bip39.json +1 -1
- package/docs/vectors/families.json +77 -77
- package/docs/vectors/kat.json +1 -1
- package/package.json +11 -3
- package/scripts/verify-core-crypto.ts +470 -17
- package/src/client/argon-auto.ts +224 -0
- package/src/client/argon-worker.ts +147 -0
- package/src/client/argon2.ts +17 -5
- package/src/client/note-crypto.ts +3 -1
- package/src/client/vault-error.ts +51 -0
- package/src/client/vault.ts +486 -0
- package/src/client/vendor/hash-wasm-argon2.ts +27 -0
- package/src/index.ts +1 -1
- package/src/server/env.ts +7 -0
- package/src/server/ratelimit.ts +48 -1
package/src/server/ratelimit.ts
CHANGED
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
* 放行判準:RETURNING 的 count <= max(窗口內超額後的每一發都回實際 count,
|
|
15
15
|
* 由呼叫端以 count <= max 拒絕——計數不封頂,超額仍逐發累計)。
|
|
16
16
|
*
|
|
17
|
+
* 限流鍵(2026-10-11 定案):checkRate 入口經 normalizeRateIp 正規化——IPv6 聚合至 /64
|
|
18
|
+
* (單一終端可自由輪換 /64 內尾段=完整地址當鍵即每發新鍵、限流失效);IPv4-mapped
|
|
19
|
+
* 位址回點分 IPv4(=原生 IPv4 同 /32 鍵,review r1 MAJOR-1 收口);IPv4 與非 IPv6 形原樣。
|
|
20
|
+
*
|
|
17
21
|
* 呼叫端須自建表(無 GC 機制:舊 IP 列不清,表隨活躍 IP 數緩慢增長——
|
|
18
22
|
* 每列 ~40 bytes,量級可忽略;如需回收見下方 GC 註記):
|
|
19
23
|
* CREATE TABLE IF NOT EXISTS {table} (ip TEXT PRIMARY KEY, window_start INTEGER, count INTEGER);
|
|
@@ -71,6 +75,49 @@ async function bumpRate(env: Env, w: RateWindow, ip: string): Promise<boolean> {
|
|
|
71
75
|
}
|
|
72
76
|
}
|
|
73
77
|
|
|
78
|
+
const HEXTET = /^[0-9a-f]{1,4}$/i;
|
|
79
|
+
const IPV4_OCTET = /^(0|[1-9]\d{0,2})$/;
|
|
80
|
+
|
|
81
|
+
/** IPv6 文字形 → 8 組 hextet 數值(RFC 4291 §2.2:`::` 至多一處、嵌入 IPv4 僅居末);非法形回 null。 */
|
|
82
|
+
function parseIpv6(s: string): number[] | null {
|
|
83
|
+
const halves = s.split('::');
|
|
84
|
+
if (halves.length > 2) return null;
|
|
85
|
+
const parts = halves.map((h) => (h === '' ? [] : h.split(':')));
|
|
86
|
+
const last = parts[parts.length - 1];
|
|
87
|
+
const v4: number[] = [];
|
|
88
|
+
if (last.length > 0 && last[last.length - 1].includes('.')) {
|
|
89
|
+
const q = last.pop()!.split('.');
|
|
90
|
+
if (q.length !== 4 || !q.every((o) => IPV4_OCTET.test(o) && Number(o) <= 255)) return null;
|
|
91
|
+
v4.push(Number(q[0]) * 256 + Number(q[1]), Number(q[2]) * 256 + Number(q[3]));
|
|
92
|
+
}
|
|
93
|
+
if (!parts.every((p) => p.every((g) => HEXTET.test(g)))) return null;
|
|
94
|
+
const n = parts.reduce((a, p) => a + p.length, 0) + v4.length;
|
|
95
|
+
const hex = (p: string[]): number[] => p.map((g) => parseInt(g, 16));
|
|
96
|
+
if (halves.length === 1) return n === 8 ? [...hex(parts[0]), ...v4] : null;
|
|
97
|
+
if (n > 7) return null;
|
|
98
|
+
return [...hex(parts[0]), ...new Array<number>(8 - n).fill(0), ...hex(parts[1]), ...v4];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* 限流鍵正規化(單一真相;純函式、零 throw):
|
|
103
|
+
* - IPv6 → /64 前綴+`/64` 標記(RFC 5952 規範形:hextet 前導零摘除、小寫、零串壓縮),
|
|
104
|
+
* 例 `2001:0DB8:0000:000A::1` → `2001:db8:0:a::/64`、`::1` → `::/64`;zone id(`%…`)先剝除。
|
|
105
|
+
* 介面 ID 歸零後末 4 組恆零=最長零串恆為尾串(前綴內零串至多 3 組),故壓縮形=前綴摘尾零組+`::`。
|
|
106
|
+
* - IPv4-mapped(::/96 前綴+映射尾組,RFC 4291 §2.5.5.2)→ 點分 IPv4 原鍵——mapped 位址就是 IPv4
|
|
107
|
+
* 節點的表示法,回 /32 與原生同鍵(hex 尾組 twin `::ffff:c000:201` 同鍵 192.0.2.1;禁併入 ::/64 全域桶)。
|
|
108
|
+
* - IPv4/`'unknown'`/空串/無法解析形:原樣返回(鍵照樣進表=可見面,不靜默丟鍵)。
|
|
109
|
+
*/
|
|
110
|
+
export function normalizeRateIp(ip: string): string {
|
|
111
|
+
if (typeof ip !== 'string' || !ip.includes(':')) return ip;
|
|
112
|
+
const pct = ip.indexOf('%');
|
|
113
|
+
const g = parseIpv6(pct >= 0 ? ip.slice(0, pct) : ip);
|
|
114
|
+
if (!g) return ip;
|
|
115
|
+
if (g[0] === 0 && g[1] === 0 && g[2] === 0 && g[3] === 0 && g[4] === 0 && g[5] === 0xffff) return [g[6] >> 8, g[6] & 255, g[7] >> 8, g[7] & 255].join('.');
|
|
116
|
+
const net = g.slice(0, 4);
|
|
117
|
+
while (net.length > 0 && net[net.length - 1] === 0) net.pop();
|
|
118
|
+
return net.map((h) => h.toString(16)).join(':') + '::/64';
|
|
119
|
+
}
|
|
120
|
+
|
|
74
121
|
export function checkRate(env: Env, w: RateWindow, ip: string): Promise<boolean> {
|
|
75
|
-
return bumpRate(env, w, ip);
|
|
122
|
+
return bumpRate(env, w, normalizeRateIp(ip));
|
|
76
123
|
}
|