@oneaddress/setup 1.1.9 → 1.2.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 +2 -2
- package/dist/index.js +43 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,8 +48,8 @@ From the [Partner Portal](https://partners.oneaddress.io) → My Profile → Int
|
|
|
48
48
|
## Documentation
|
|
49
49
|
|
|
50
50
|
- [Partner Portal](https://partners.oneaddress.io)
|
|
51
|
-
- [Protocol Specification](https://github.com/oneaddress-io/oneaddress-app/blob/main/docs/
|
|
52
|
-
- [Service Level Objectives](https://github.com/oneaddress-io/oneaddress-app/blob/main/docs/
|
|
51
|
+
- [Protocol Specification](https://github.com/oneaddress-io/oneaddress-app/blob/main/docs/integrations/SPEC.md)
|
|
52
|
+
- [Service Level Objectives](https://github.com/oneaddress-io/oneaddress-app/blob/main/docs/integrations/SLOS.md)
|
|
53
53
|
|
|
54
54
|
## Issues
|
|
55
55
|
|
package/dist/index.js
CHANGED
|
@@ -835,7 +835,7 @@ var _R = ["\u2588\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588"
|
|
|
835
835
|
var _S = [" \u2588\u2588\u2588\u2588\u2588\u2588", "\u2588\u2588 ", "\u2588\u2588 ", " \u2588\u2588\u2588\u2588\u2588 ", " \u2588\u2588", " \u2588\u2588", "\u2588\u2588\u2588\u2588\u2588\u2588 "];
|
|
836
836
|
var ONE_ROWS = Array.from({ length: 7 }, (_2, i) => [_O[i], _N[i], _E[i]].join(" "));
|
|
837
837
|
var ADDR_ROWS = Array.from({ length: 7 }, (_2, i) => [_A[i], _D2[i], _D2[i], _R[i], _E[i], _S[i], _S[i]].join(" "));
|
|
838
|
-
var WIZARD_VERSION = true ? "1.
|
|
838
|
+
var WIZARD_VERSION = true ? "1.2.0" : "?";
|
|
839
839
|
function printHeader() {
|
|
840
840
|
const BAR_LEN = 85;
|
|
841
841
|
const TOP_BAR = fn("\u250C") + dm("\u2500".repeat(BAR_LEN)) + fn("\u2510");
|
|
@@ -860,7 +860,7 @@ function printHeader() {
|
|
|
860
860
|
console.log("");
|
|
861
861
|
}
|
|
862
862
|
function stripAnsi(s) {
|
|
863
|
-
return s.
|
|
863
|
+
return s.replaceAll(/\x1b\[[0-9;]*m/g, "");
|
|
864
864
|
}
|
|
865
865
|
|
|
866
866
|
// src/scaffold.ts
|
|
@@ -1091,7 +1091,13 @@ if (nodeMajor < 22 || (nodeMajor === 22 && nodeMinor < 5)) {
|
|
|
1091
1091
|
|
|
1092
1092
|
import 'dotenv/config';
|
|
1093
1093
|
import express, { Request, Response } from 'express';
|
|
1094
|
-
import {
|
|
1094
|
+
import {
|
|
1095
|
+
verifySignature,
|
|
1096
|
+
decryptAddress,
|
|
1097
|
+
decryptSession,
|
|
1098
|
+
isFreshTimestamp,
|
|
1099
|
+
type SessionKeyShare,
|
|
1100
|
+
} from '@oneaddress/partner-sdk';
|
|
1095
1101
|
import { saveAddress, verifyAddress } from './store.js';
|
|
1096
1102
|
|
|
1097
1103
|
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET ?? '';
|
|
@@ -1137,23 +1143,43 @@ app.post('/webhook', async (req: Request, res: Response) => {
|
|
|
1137
1143
|
}
|
|
1138
1144
|
if (dispatch) seenDispatches.add(dispatch);
|
|
1139
1145
|
|
|
1140
|
-
// 5. Decrypt address payload
|
|
1141
|
-
|
|
1146
|
+
// 5. Decrypt address payload. Two shapes possible:
|
|
1147
|
+
// (a) D5 (new, 2026+): body.session_envelope + body.session_key_share.
|
|
1148
|
+
// (b) Legacy: body.address_encrypted.
|
|
1149
|
+
// A webhook will carry exactly one shape. If you've registered multiple
|
|
1150
|
+
// versioned keys (D5 supports key rotation with 90-day overlap), look up
|
|
1151
|
+
// the right private key by session_key_share.key_id from your key store.
|
|
1152
|
+
// This scaffold uses a single PARTNER_PRIVATE_KEY_PEM for simplicity \u2014
|
|
1153
|
+
// production deployments should hold a Map<key_id, privateKeyPem>.
|
|
1154
|
+
let address: Record<string, unknown>;
|
|
1155
|
+
|
|
1156
|
+
const sessionEnvelope = typeof body.session_envelope === 'string' ? body.session_envelope : null;
|
|
1157
|
+
const sessionKeyShare = body.session_key_share as SessionKeyShare | undefined;
|
|
1158
|
+
const legacyPayload = body.address_encrypted as {
|
|
1142
1159
|
ephemeralPublicKey: string; iv: string; ciphertext: string; hkdfSalt?: string;
|
|
1143
1160
|
} | null;
|
|
1144
1161
|
|
|
1145
|
-
if (
|
|
1162
|
+
if (sessionEnvelope && sessionKeyShare) {
|
|
1163
|
+
// D5 \u2014 call decryptSession. Wrong key_id / wrong partner_id / tampered
|
|
1164
|
+
// ciphertext all surface as an AES-GCM authentication-tag error.
|
|
1165
|
+
try {
|
|
1166
|
+
const data = await decryptSession(sessionKeyShare, sessionEnvelope, PARTNER_PRIVATE_KEY, PARTNER_ID);
|
|
1167
|
+
address = data.new_address as unknown as Record<string, unknown>;
|
|
1168
|
+
} catch (err) {
|
|
1169
|
+
console.error('[webhook] D5 decryption failed \u2014 check PARTNER_PRIVATE_KEY_PEM matches key_id', sessionKeyShare.key_id, ':', err);
|
|
1170
|
+
return res.status(200).json({ ok: true, note: 'Received \u2014 D5 decryption pending key setup' });
|
|
1171
|
+
}
|
|
1172
|
+
} else if (legacyPayload) {
|
|
1173
|
+
try {
|
|
1174
|
+
address = await decryptAddress(legacyPayload, PARTNER_PRIVATE_KEY, PARTNER_ID);
|
|
1175
|
+
} catch (err) {
|
|
1176
|
+
console.error('[webhook] Decryption failed \u2014 check PARTNER_PRIVATE_KEY_PEM in .env:', err);
|
|
1177
|
+
return res.status(200).json({ ok: true, note: 'Received \u2014 decryption pending key setup' });
|
|
1178
|
+
}
|
|
1179
|
+
} else {
|
|
1146
1180
|
return res.status(200).json({ ok: true, note: 'No encrypted payload' });
|
|
1147
1181
|
}
|
|
1148
1182
|
|
|
1149
|
-
let address: Record<string, unknown>;
|
|
1150
|
-
try {
|
|
1151
|
-
address = await decryptAddress(encPayload, PARTNER_PRIVATE_KEY, PARTNER_ID);
|
|
1152
|
-
} catch (err) {
|
|
1153
|
-
console.error('[webhook] Decryption failed \u2014 check PARTNER_PRIVATE_KEY_PEM in .env:', err);
|
|
1154
|
-
return res.status(200).json({ ok: true, note: 'Received \u2014 decryption pending key setup' });
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
1183
|
const event = body.event as string;
|
|
1158
1184
|
const customer = body.customer as { email?: string; name?: string } | undefined;
|
|
1159
1185
|
const ctx = { email: customer?.email ?? '', name: customer?.name ?? '' };
|
|
@@ -3393,7 +3419,7 @@ function normalisePrivateKey(raw) {
|
|
|
3393
3419
|
if (!(0, import_node_fs4.existsSync)(abs)) return { pem: "", error: `File not found: ${abs}` };
|
|
3394
3420
|
return normalisePrivateKey((0, import_node_fs4.readFileSync)(abs, "utf8"));
|
|
3395
3421
|
}
|
|
3396
|
-
const unescaped = trimmed.
|
|
3422
|
+
const unescaped = trimmed.replaceAll(/\\n/g, "\n");
|
|
3397
3423
|
if (unescaped.includes("-----BEGIN PRIVATE KEY-----")) {
|
|
3398
3424
|
return { pem: unescaped };
|
|
3399
3425
|
}
|
|
@@ -3413,7 +3439,7 @@ function normalisePrivateKey(raw) {
|
|
|
3413
3439
|
if (b64Lines.length === 0) return { pem: "", error: "Could not extract key body from the OneAddress PEM file" };
|
|
3414
3440
|
return wrapAsPkcs8(b64Lines.join(""));
|
|
3415
3441
|
}
|
|
3416
|
-
const b64clean = trimmed.
|
|
3442
|
+
const b64clean = trimmed.replaceAll(/\s+/g, "");
|
|
3417
3443
|
if (/^[A-Za-z0-9+/]+=*$/.test(b64clean) && b64clean.length >= 50) {
|
|
3418
3444
|
return wrapAsPkcs8(b64clean);
|
|
3419
3445
|
}
|
|
@@ -3650,7 +3676,7 @@ Continuing will overwrite it.`
|
|
|
3650
3676
|
`Files in: ${outDir}`
|
|
3651
3677
|
].join("\n");
|
|
3652
3678
|
const nextSteps = [
|
|
3653
|
-
"1. Trigger a live event: update your address at
|
|
3679
|
+
"1. Trigger a live event: update your address at oneaddress.io\n \u2192 src/store.ts will save it to data.db automatically",
|
|
3654
3680
|
"2. View your database: open data.db with DB Browser for SQLite\n (free download at sqlitebrowser.org)",
|
|
3655
3681
|
"3. For production: swap src/store.ts for your real database (Postgres, MySQL, etc.)\n then deploy and update the webhook URL in the portal",
|
|
3656
3682
|
"4. Questions? partners.oneaddress.io or partners@oneaddress.io"
|