@kraki/head 0.4.1 → 0.9.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/dist/auth.d.ts +1 -0
- package/dist/auth.js +3 -0
- package/dist/auth.js.map +1 -1
- package/dist/cli.js +61 -0
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/push/apns.d.ts +32 -0
- package/dist/push/apns.js +144 -0
- package/dist/push/apns.js.map +1 -0
- package/dist/push/index.d.ts +17 -0
- package/dist/push/index.js +60 -0
- package/dist/push/index.js.map +1 -0
- package/dist/push/provider.d.ts +27 -0
- package/dist/push/provider.js +5 -0
- package/dist/push/provider.js.map +1 -0
- package/dist/push/web-push.d.ts +15 -0
- package/dist/push/web-push.js +45 -0
- package/dist/push/web-push.js.map +1 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.js +123 -14
- package/dist/server.js.map +1 -1
- package/dist/storage.d.ts +25 -0
- package/dist/storage.js +109 -1
- package/dist/storage.js.map +1 -1
- package/package.json +4 -2
package/dist/auth.d.ts
CHANGED
|
@@ -97,6 +97,7 @@ export declare class ThrottledAuthProvider implements AuthProvider {
|
|
|
97
97
|
private maxAttempts;
|
|
98
98
|
private windowMs;
|
|
99
99
|
private failures;
|
|
100
|
+
private cleanupTimer;
|
|
100
101
|
constructor(inner: AuthProvider, maxAttempts?: number, windowMs?: number);
|
|
101
102
|
authenticate(credentials: AuthCredentials): Promise<AuthOutcome>;
|
|
102
103
|
/** Remove stale entries to prevent memory growth on long-running servers. */
|
package/dist/auth.js
CHANGED
|
@@ -167,10 +167,13 @@ export class ThrottledAuthProvider {
|
|
|
167
167
|
maxAttempts;
|
|
168
168
|
windowMs;
|
|
169
169
|
failures = new Map();
|
|
170
|
+
cleanupTimer;
|
|
170
171
|
constructor(inner, maxAttempts = 5, windowMs = 60_000) {
|
|
171
172
|
this.inner = inner;
|
|
172
173
|
this.maxAttempts = maxAttempts;
|
|
173
174
|
this.windowMs = windowMs;
|
|
175
|
+
this.cleanupTimer = setInterval(() => this.cleanup(), windowMs * 2);
|
|
176
|
+
this.cleanupTimer.unref();
|
|
174
177
|
}
|
|
175
178
|
async authenticate(credentials) {
|
|
176
179
|
const ip = credentials.ip ?? 'unknown';
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -30,6 +30,7 @@ import { Storage } from './storage.js';
|
|
|
30
30
|
import { HeadServer } from './server.js';
|
|
31
31
|
import { GitHubAuthProvider, OpenAuthProvider, ApiKeyAuthProvider, ThrottledAuthProvider } from './auth.js';
|
|
32
32
|
import { Logger, setGlobalLogger } from './logger.js';
|
|
33
|
+
import { PushManager, ApnsProvider, WebPushProvider } from './push/index.js';
|
|
33
34
|
// --- CLI flags ---
|
|
34
35
|
const args = process.argv.slice(2);
|
|
35
36
|
if (args.includes('--help') || args.includes('-h')) {
|
|
@@ -42,6 +43,7 @@ if (args.includes('--help') || args.includes('-h')) {
|
|
|
42
43
|
--port <n> Server port (default: 4000, env: PORT)
|
|
43
44
|
--db <path> SQLite database path (default: kraki-head.db, env: DB_PATH)
|
|
44
45
|
--auth <mode> Auth mode: open | github | apikey (default: open, env: AUTH_MODE)
|
|
46
|
+
--push <type> Push providers: apns,web_push (comma-separated, env: PUSH_PROVIDERS)
|
|
45
47
|
--log <level> Log level: debug | info | warn | error (default: info)
|
|
46
48
|
--help, -h Show this help
|
|
47
49
|
--version, -v Show version
|
|
@@ -49,6 +51,18 @@ if (args.includes('--help') || args.includes('-h')) {
|
|
|
49
51
|
GitHub OAuth (env only, for web login):
|
|
50
52
|
GITHUB_CLIENT_ID GitHub OAuth App client ID
|
|
51
53
|
GITHUB_CLIENT_SECRET GitHub OAuth App client secret
|
|
54
|
+
|
|
55
|
+
APNs push notifications (env only):
|
|
56
|
+
APNS_KEY_PATH Path to .p8 private key file
|
|
57
|
+
APNS_KEY_ID Key ID from Apple Developer
|
|
58
|
+
APNS_TEAM_ID Team ID from Apple Developer
|
|
59
|
+
APNS_BUNDLE_ID App bundle ID (APNs topic)
|
|
60
|
+
APNS_ENVIRONMENT production | sandbox (default: production)
|
|
61
|
+
|
|
62
|
+
Web Push / VAPID (env only):
|
|
63
|
+
VAPID_PUBLIC_KEY VAPID public key (base64url, from web-push generate-vapid-keys)
|
|
64
|
+
VAPID_PRIVATE_KEY VAPID private key (base64url)
|
|
65
|
+
VAPID_EMAIL Contact email (e.g. mailto:admin@example.com)
|
|
52
66
|
`);
|
|
53
67
|
process.exit(0);
|
|
54
68
|
}
|
|
@@ -63,6 +77,10 @@ function flag(name, fallback) {
|
|
|
63
77
|
return args[i + 1] || fallback;
|
|
64
78
|
}
|
|
65
79
|
const PORT = parseInt(flag('port', process.env.PORT || '4000'), 10);
|
|
80
|
+
if (isNaN(PORT) || PORT < 1 || PORT > 65535) {
|
|
81
|
+
console.error(`Invalid port: ${flag('port', process.env.PORT || '4000')}. Must be 1-65535.`);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
66
84
|
const DB_PATH = flag('db', process.env.DB_PATH || 'kraki-head.db');
|
|
67
85
|
const AUTH_MODES = flag('auth', process.env.AUTH_MODE || 'open').split(',').map(s => s.trim());
|
|
68
86
|
const API_KEY = process.env.API_KEY;
|
|
@@ -71,6 +89,7 @@ const GITHUB_CLIENT_SECRET = process.env.GITHUB_CLIENT_SECRET;
|
|
|
71
89
|
const PAIRING = process.env.PAIRING_ENABLED !== 'false'; // default true
|
|
72
90
|
const LOG_LEVEL = flag('log', process.env.LOG_LEVEL || 'info');
|
|
73
91
|
const LOG_PATH = process.env.LOG_PATH;
|
|
92
|
+
const PUSH_PROVIDERS = flag('push', process.env.PUSH_PROVIDERS || '').split(',').map(s => s.trim()).filter(Boolean);
|
|
74
93
|
function createAuthProviders() {
|
|
75
94
|
const providers = new Map();
|
|
76
95
|
for (const mode of AUTH_MODES) {
|
|
@@ -117,10 +136,52 @@ setGlobalLogger(logger);
|
|
|
117
136
|
logger.info('Kraki Head starting...');
|
|
118
137
|
const authProviders = createAuthProviders();
|
|
119
138
|
const storage = new Storage(DB_PATH);
|
|
139
|
+
// --- Push providers ---
|
|
140
|
+
let pushManager;
|
|
141
|
+
if (PUSH_PROVIDERS.length > 0) {
|
|
142
|
+
const pushProviderInstances = [];
|
|
143
|
+
for (const provider of PUSH_PROVIDERS) {
|
|
144
|
+
switch (provider) {
|
|
145
|
+
case 'apns': {
|
|
146
|
+
const keyPath = process.env.APNS_KEY_PATH;
|
|
147
|
+
const keyId = process.env.APNS_KEY_ID;
|
|
148
|
+
const teamId = process.env.APNS_TEAM_ID;
|
|
149
|
+
const bundleId = process.env.APNS_BUNDLE_ID;
|
|
150
|
+
if (!keyPath || !keyId || !teamId || !bundleId) {
|
|
151
|
+
console.error('Error: APNs requires APNS_KEY_PATH, APNS_KEY_ID, APNS_TEAM_ID, APNS_BUNDLE_ID');
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
154
|
+
pushProviderInstances.push(new ApnsProvider({
|
|
155
|
+
keyPath, keyId, teamId, bundleId,
|
|
156
|
+
environment: process.env.APNS_ENVIRONMENT ?? 'production',
|
|
157
|
+
}));
|
|
158
|
+
logger.info('APNs push provider configured', { bundleId, environment: process.env.APNS_ENVIRONMENT ?? 'production' });
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
case 'web_push': {
|
|
162
|
+
const vapidPublicKey = process.env.VAPID_PUBLIC_KEY;
|
|
163
|
+
const vapidPrivateKey = process.env.VAPID_PRIVATE_KEY;
|
|
164
|
+
const vapidEmail = process.env.VAPID_EMAIL;
|
|
165
|
+
if (!vapidPublicKey || !vapidPrivateKey || !vapidEmail) {
|
|
166
|
+
console.error('Error: Web Push requires VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, VAPID_EMAIL');
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
pushProviderInstances.push(new WebPushProvider({ vapidPublicKey, vapidPrivateKey, vapidEmail }));
|
|
170
|
+
logger.info('Web Push provider configured', { email: vapidEmail });
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
default:
|
|
174
|
+
console.error(`Error: Unknown push provider '${provider}'. Use: apns, web_push`);
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
pushManager = new PushManager(storage, pushProviderInstances);
|
|
179
|
+
}
|
|
120
180
|
const head = new HeadServer(storage, {
|
|
121
181
|
authProviders,
|
|
122
182
|
pairingEnabled: PAIRING,
|
|
123
183
|
version: VERSION,
|
|
184
|
+
pushManager,
|
|
124
185
|
});
|
|
125
186
|
const httpServer = createServer((req, res) => {
|
|
126
187
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,sEAAsE;AACtE,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,YAAY,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;AAEzD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AACxF,MAAM,OAAO,GAAW,GAAG,CAAC,OAAO,CAAC;AAEpC,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAE5G,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
export { Storage } from './storage.js';
|
|
2
|
+
export type { StoredDevice, StoredUser, StoredPushToken } from './storage.js';
|
|
2
3
|
export { HeadServer } from './server.js';
|
|
3
4
|
export type { HeadServerOptions } from './server.js';
|
|
4
5
|
export { GitHubAuthProvider, OpenAuthProvider, ApiKeyAuthProvider, ThrottledAuthProvider } from './auth.js';
|
|
5
6
|
export type { AuthProvider, AuthUser, AuthOutcome, AuthCredentials } from './auth.js';
|
|
6
7
|
export { Logger, getLogger, setGlobalLogger } from './logger.js';
|
|
7
8
|
export type { LoggerOptions, LogLevel } from './logger.js';
|
|
9
|
+
export { PushManager, ApnsProvider, WebPushProvider } from './push/index.js';
|
|
10
|
+
export type { PushProvider, PushPayload, PushResult, ApnsConfig, WebPushConfig } from './push/index.js';
|
package/dist/index.js
CHANGED
|
@@ -2,4 +2,5 @@ export { Storage } from './storage.js';
|
|
|
2
2
|
export { HeadServer } from './server.js';
|
|
3
3
|
export { GitHubAuthProvider, OpenAuthProvider, ApiKeyAuthProvider, ThrottledAuthProvider } from './auth.js';
|
|
4
4
|
export { Logger, getLogger, setGlobalLogger } from './logger.js';
|
|
5
|
+
export { PushManager, ApnsProvider, WebPushProvider } from './push/index.js';
|
|
5
6
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAE5G,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { PushPayload, PushProvider, PushResult } from './provider.js';
|
|
2
|
+
export interface ApnsConfig {
|
|
3
|
+
/** Path to the .p8 private key file */
|
|
4
|
+
keyPath: string;
|
|
5
|
+
/** Key ID from Apple Developer */
|
|
6
|
+
keyId: string;
|
|
7
|
+
/** Team ID from Apple Developer */
|
|
8
|
+
teamId: string;
|
|
9
|
+
/** Default bundle ID (APNs topic) */
|
|
10
|
+
bundleId: string;
|
|
11
|
+
/** Default environment */
|
|
12
|
+
environment?: 'production' | 'sandbox';
|
|
13
|
+
}
|
|
14
|
+
export declare class ApnsProvider implements PushProvider {
|
|
15
|
+
readonly name = "apns";
|
|
16
|
+
private readonly key;
|
|
17
|
+
private readonly keyId;
|
|
18
|
+
private readonly teamId;
|
|
19
|
+
private readonly defaultBundleId;
|
|
20
|
+
private readonly defaultEnvironment;
|
|
21
|
+
private sessions;
|
|
22
|
+
private jwt;
|
|
23
|
+
constructor(config: ApnsConfig);
|
|
24
|
+
send(token: string, payload: PushPayload, opts?: {
|
|
25
|
+
environment?: string;
|
|
26
|
+
bundleId?: string;
|
|
27
|
+
}): Promise<PushResult>;
|
|
28
|
+
private sendRaw;
|
|
29
|
+
private getSession;
|
|
30
|
+
private getJwt;
|
|
31
|
+
close(): void;
|
|
32
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// ------------------------------------------------------------
|
|
2
|
+
// APNs push provider — HTTP/2 + JWT
|
|
3
|
+
// ------------------------------------------------------------
|
|
4
|
+
import { createSign } from 'node:crypto';
|
|
5
|
+
import http2 from 'node:http2';
|
|
6
|
+
import { readFileSync } from 'node:fs';
|
|
7
|
+
import { getLogger } from '../logger.js';
|
|
8
|
+
const APNS_HOST_PRODUCTION = 'api.push.apple.com';
|
|
9
|
+
const APNS_HOST_SANDBOX = 'api.sandbox.push.apple.com';
|
|
10
|
+
const JWT_ALGORITHM = 'ES256';
|
|
11
|
+
const JWT_TTL_MS = 50 * 60 * 1000; // Refresh JWT every 50 minutes (APNs requires < 1 hour)
|
|
12
|
+
export class ApnsProvider {
|
|
13
|
+
name = 'apns';
|
|
14
|
+
key;
|
|
15
|
+
keyId;
|
|
16
|
+
teamId;
|
|
17
|
+
defaultBundleId;
|
|
18
|
+
defaultEnvironment;
|
|
19
|
+
sessions = new Map();
|
|
20
|
+
jwt = null;
|
|
21
|
+
constructor(config) {
|
|
22
|
+
this.key = readFileSync(config.keyPath, 'utf8');
|
|
23
|
+
this.keyId = config.keyId;
|
|
24
|
+
this.teamId = config.teamId;
|
|
25
|
+
this.defaultBundleId = config.bundleId;
|
|
26
|
+
this.defaultEnvironment = config.environment ?? 'production';
|
|
27
|
+
}
|
|
28
|
+
async send(token, payload, opts) {
|
|
29
|
+
const logger = getLogger();
|
|
30
|
+
const env = (opts?.environment ?? this.defaultEnvironment);
|
|
31
|
+
const bundleId = opts?.bundleId ?? this.defaultBundleId;
|
|
32
|
+
const host = env === 'sandbox' ? APNS_HOST_SANDBOX : APNS_HOST_PRODUCTION;
|
|
33
|
+
const apnsPayload = JSON.stringify({
|
|
34
|
+
aps: {
|
|
35
|
+
alert: { title: 'Kraki', body: 'Needs your attention' },
|
|
36
|
+
'mutable-content': 1,
|
|
37
|
+
},
|
|
38
|
+
kraki: {
|
|
39
|
+
blob: payload.blob,
|
|
40
|
+
key: payload.key,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
// Check 4KB APNs limit
|
|
44
|
+
if (Buffer.byteLength(apnsPayload) > 4096) {
|
|
45
|
+
logger.warn('APNs payload exceeds 4KB, sending without preview', { tokenSuffix: token.slice(-8) });
|
|
46
|
+
// Fall back to opaque notification without preview data
|
|
47
|
+
const fallback = JSON.stringify({
|
|
48
|
+
aps: {
|
|
49
|
+
alert: { title: 'Kraki', body: 'Needs your attention' },
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
return this.sendRaw(host, token, bundleId, fallback);
|
|
53
|
+
}
|
|
54
|
+
return this.sendRaw(host, token, bundleId, apnsPayload);
|
|
55
|
+
}
|
|
56
|
+
async sendRaw(host, token, bundleId, body) {
|
|
57
|
+
const logger = getLogger();
|
|
58
|
+
const jwt = this.getJwt();
|
|
59
|
+
const session = this.getSession(host);
|
|
60
|
+
return new Promise((resolve) => {
|
|
61
|
+
const req = session.request({
|
|
62
|
+
':method': 'POST',
|
|
63
|
+
':path': `/3/device/${token}`,
|
|
64
|
+
'authorization': `bearer ${jwt}`,
|
|
65
|
+
'apns-topic': bundleId,
|
|
66
|
+
'apns-push-type': 'alert',
|
|
67
|
+
'apns-priority': '10',
|
|
68
|
+
'content-type': 'application/json',
|
|
69
|
+
});
|
|
70
|
+
let responseData = '';
|
|
71
|
+
let statusCode = 0;
|
|
72
|
+
req.on('response', (headers) => {
|
|
73
|
+
statusCode = headers[':status'];
|
|
74
|
+
});
|
|
75
|
+
req.on('data', (chunk) => {
|
|
76
|
+
responseData += chunk.toString();
|
|
77
|
+
});
|
|
78
|
+
req.on('end', () => {
|
|
79
|
+
if (statusCode === 200) {
|
|
80
|
+
resolve({ success: true });
|
|
81
|
+
}
|
|
82
|
+
else if (statusCode === 410) {
|
|
83
|
+
logger.info('APNs token gone (410), marking for removal', { tokenSuffix: token.slice(-8) });
|
|
84
|
+
resolve({ success: false, gone: true, error: 'Token no longer valid' });
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
let errorReason = `HTTP ${statusCode}`;
|
|
88
|
+
try {
|
|
89
|
+
const parsed = JSON.parse(responseData);
|
|
90
|
+
if (parsed.reason)
|
|
91
|
+
errorReason = parsed.reason;
|
|
92
|
+
}
|
|
93
|
+
catch { /* ignore parse errors */ }
|
|
94
|
+
logger.warn('APNs send failed', { status: statusCode, reason: errorReason, tokenSuffix: token.slice(-8) });
|
|
95
|
+
resolve({ success: false, error: errorReason });
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
req.on('error', (err) => {
|
|
99
|
+
logger.error('APNs request error', { error: err.message, tokenSuffix: token.slice(-8) });
|
|
100
|
+
resolve({ success: false, error: err.message });
|
|
101
|
+
});
|
|
102
|
+
req.end(body);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
getSession(host) {
|
|
106
|
+
let session = this.sessions.get(host);
|
|
107
|
+
if (session && !session.destroyed && !session.closed)
|
|
108
|
+
return session;
|
|
109
|
+
session = http2.connect(`https://${host}`);
|
|
110
|
+
session.on('error', () => {
|
|
111
|
+
this.sessions.delete(host);
|
|
112
|
+
});
|
|
113
|
+
session.on('close', () => {
|
|
114
|
+
this.sessions.delete(host);
|
|
115
|
+
});
|
|
116
|
+
this.sessions.set(host, session);
|
|
117
|
+
return session;
|
|
118
|
+
}
|
|
119
|
+
getJwt() {
|
|
120
|
+
const now = Date.now();
|
|
121
|
+
if (this.jwt && now - this.jwt.issuedAt < JWT_TTL_MS) {
|
|
122
|
+
return this.jwt.token;
|
|
123
|
+
}
|
|
124
|
+
const issuedAt = Math.floor(now / 1000);
|
|
125
|
+
const header = Buffer.from(JSON.stringify({ alg: JWT_ALGORITHM, kid: this.keyId })).toString('base64url');
|
|
126
|
+
const payload = Buffer.from(JSON.stringify({ iss: this.teamId, iat: issuedAt })).toString('base64url');
|
|
127
|
+
const signer = createSign('SHA256');
|
|
128
|
+
signer.update(`${header}.${payload}`);
|
|
129
|
+
const signature = signer.sign(this.key, 'base64url');
|
|
130
|
+
const token = `${header}.${payload}.${signature}`;
|
|
131
|
+
this.jwt = { token, issuedAt: now };
|
|
132
|
+
return token;
|
|
133
|
+
}
|
|
134
|
+
close() {
|
|
135
|
+
for (const session of this.sessions.values()) {
|
|
136
|
+
try {
|
|
137
|
+
session.close();
|
|
138
|
+
}
|
|
139
|
+
catch { /* best effort */ }
|
|
140
|
+
}
|
|
141
|
+
this.sessions.clear();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=apns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apns.js","sourceRoot":"","sources":["../../src/push/apns.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Storage } from '../storage.js';
|
|
2
|
+
import type { PushProvider } from './provider.js';
|
|
3
|
+
import type { BlobPayload } from '@kraki/protocol';
|
|
4
|
+
export declare class PushManager {
|
|
5
|
+
private storage;
|
|
6
|
+
private providers;
|
|
7
|
+
constructor(storage: Storage, providers: PushProvider[]);
|
|
8
|
+
/** Send push notifications to all offline devices with registered tokens. */
|
|
9
|
+
sendToOfflineDevices(userId: string, onlineDeviceIds: string[], pushPreview: BlobPayload): Promise<void>;
|
|
10
|
+
private sendToDevice;
|
|
11
|
+
close(): void;
|
|
12
|
+
/** Get the VAPID public key if a web_push provider is configured. */
|
|
13
|
+
getVapidPublicKey(): string | undefined;
|
|
14
|
+
}
|
|
15
|
+
export { type PushProvider, type PushPayload, type PushResult } from './provider.js';
|
|
16
|
+
export { ApnsProvider, type ApnsConfig } from './apns.js';
|
|
17
|
+
export { WebPushProvider, type WebPushConfig } from './web-push.js';
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// ------------------------------------------------------------
|
|
2
|
+
// PushManager — coordinates push providers and token storage
|
|
3
|
+
// ------------------------------------------------------------
|
|
4
|
+
import { getLogger } from '../logger.js';
|
|
5
|
+
export class PushManager {
|
|
6
|
+
storage;
|
|
7
|
+
providers = new Map();
|
|
8
|
+
constructor(storage, providers) {
|
|
9
|
+
this.storage = storage;
|
|
10
|
+
for (const p of providers) {
|
|
11
|
+
this.providers.set(p.name, p);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/** Send push notifications to all offline devices with registered tokens. */
|
|
15
|
+
async sendToOfflineDevices(userId, onlineDeviceIds, pushPreview) {
|
|
16
|
+
const logger = getLogger();
|
|
17
|
+
const tokens = this.storage.getPushTokensForOfflineDevices(userId, onlineDeviceIds);
|
|
18
|
+
if (tokens.length === 0)
|
|
19
|
+
return;
|
|
20
|
+
const results = await Promise.allSettled(tokens.map(token => this.sendToDevice(token, pushPreview)));
|
|
21
|
+
for (let i = 0; i < results.length; i++) {
|
|
22
|
+
const result = results[i];
|
|
23
|
+
const token = tokens[i];
|
|
24
|
+
if (result.status === 'rejected') {
|
|
25
|
+
logger.warn('Push send threw unexpectedly', { deviceId: token.deviceId, provider: token.provider, error: result.reason });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async sendToDevice(storedToken, pushPreview) {
|
|
30
|
+
const logger = getLogger();
|
|
31
|
+
const provider = this.providers.get(storedToken.provider);
|
|
32
|
+
if (!provider) {
|
|
33
|
+
logger.debug('No push provider for type', { provider: storedToken.provider });
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const deviceKey = pushPreview.keys[storedToken.deviceId];
|
|
37
|
+
if (!deviceKey) {
|
|
38
|
+
logger.debug('No push preview key for device', { deviceId: storedToken.deviceId });
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const result = await provider.send(storedToken.token, { blob: pushPreview.blob, key: deviceKey }, { environment: storedToken.environment ?? undefined, bundleId: storedToken.bundleId ?? undefined });
|
|
42
|
+
if (result.gone) {
|
|
43
|
+
this.storage.deletePushToken(storedToken.deviceId, storedToken.provider);
|
|
44
|
+
logger.info('Removed stale push token', { deviceId: storedToken.deviceId, provider: storedToken.provider });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
close() {
|
|
48
|
+
for (const provider of this.providers.values()) {
|
|
49
|
+
provider.close?.();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/** Get the VAPID public key if a web_push provider is configured. */
|
|
53
|
+
getVapidPublicKey() {
|
|
54
|
+
const wp = this.providers.get('web_push');
|
|
55
|
+
return wp?.vapidPublicKey;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export { ApnsProvider } from './apns.js';
|
|
59
|
+
export { WebPushProvider } from './web-push.js';
|
|
60
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/push/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Payload forwarded to the push service — encrypted, opaque to the relay. */
|
|
2
|
+
export interface PushPayload {
|
|
3
|
+
/** Encrypted preview blob (base64) */
|
|
4
|
+
blob: string;
|
|
5
|
+
/** RSA-wrapped AES key for this specific device (base64) */
|
|
6
|
+
key: string;
|
|
7
|
+
}
|
|
8
|
+
/** Result of a push send attempt. */
|
|
9
|
+
export interface PushResult {
|
|
10
|
+
success: boolean;
|
|
11
|
+
/** Error message if send failed */
|
|
12
|
+
error?: string;
|
|
13
|
+
/** True if the token is permanently invalid (e.g. APNs 410 Gone) — caller should delete it */
|
|
14
|
+
gone?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** Abstract push notification provider. Implement for each push service. */
|
|
17
|
+
export interface PushProvider {
|
|
18
|
+
/** Provider name — must match the token's provider field (e.g. 'apns') */
|
|
19
|
+
readonly name: string;
|
|
20
|
+
/** Send an encrypted preview payload to a device. */
|
|
21
|
+
send(token: string, payload: PushPayload, opts?: {
|
|
22
|
+
environment?: string;
|
|
23
|
+
bundleId?: string;
|
|
24
|
+
}): Promise<PushResult>;
|
|
25
|
+
/** Clean up resources (e.g. HTTP/2 sessions). */
|
|
26
|
+
close?(): void;
|
|
27
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/push/provider.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,uCAAuC;AACvC,+DAA+D"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PushPayload, PushProvider, PushResult } from './provider.js';
|
|
2
|
+
export interface WebPushConfig {
|
|
3
|
+
/** VAPID public key (base64url) */
|
|
4
|
+
vapidPublicKey: string;
|
|
5
|
+
/** VAPID private key (base64url) */
|
|
6
|
+
vapidPrivateKey: string;
|
|
7
|
+
/** Contact email for VAPID (e.g. "mailto:admin@kraki.dev") */
|
|
8
|
+
vapidEmail: string;
|
|
9
|
+
}
|
|
10
|
+
export declare class WebPushProvider implements PushProvider {
|
|
11
|
+
readonly name = "web_push";
|
|
12
|
+
readonly vapidPublicKey: string;
|
|
13
|
+
constructor(config: WebPushConfig);
|
|
14
|
+
send(token: string, payload: PushPayload): Promise<PushResult>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// ------------------------------------------------------------
|
|
2
|
+
// Web Push provider — VAPID + web-push library
|
|
3
|
+
// ------------------------------------------------------------
|
|
4
|
+
import webpush from 'web-push';
|
|
5
|
+
import { getLogger } from '../logger.js';
|
|
6
|
+
export class WebPushProvider {
|
|
7
|
+
name = 'web_push';
|
|
8
|
+
vapidPublicKey;
|
|
9
|
+
constructor(config) {
|
|
10
|
+
this.vapidPublicKey = config.vapidPublicKey;
|
|
11
|
+
webpush.setVapidDetails(config.vapidEmail, config.vapidPublicKey, config.vapidPrivateKey);
|
|
12
|
+
}
|
|
13
|
+
async send(token, payload) {
|
|
14
|
+
const logger = getLogger();
|
|
15
|
+
let subscription;
|
|
16
|
+
try {
|
|
17
|
+
subscription = JSON.parse(token);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
logger.warn('Invalid web push subscription JSON', { tokenPrefix: token.slice(0, 30) });
|
|
21
|
+
return { success: false, gone: true, error: 'Invalid subscription JSON' };
|
|
22
|
+
}
|
|
23
|
+
const pushPayload = JSON.stringify({
|
|
24
|
+
kraki: { blob: payload.blob, key: payload.key },
|
|
25
|
+
});
|
|
26
|
+
try {
|
|
27
|
+
await webpush.sendNotification(subscription, pushPayload, { TTL: 3600 });
|
|
28
|
+
return { success: true };
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
const statusCode = err.statusCode;
|
|
32
|
+
const body = err.body;
|
|
33
|
+
if (statusCode === 404 || statusCode === 410) {
|
|
34
|
+
logger.info('Web push subscription expired', { endpoint: subscription.endpoint?.slice(-30) });
|
|
35
|
+
return { success: false, gone: true, error: 'Subscription expired' };
|
|
36
|
+
}
|
|
37
|
+
logger.warn('Web push send failed', {
|
|
38
|
+
status: statusCode,
|
|
39
|
+
error: err.message || body || String(err),
|
|
40
|
+
});
|
|
41
|
+
return { success: false, error: err.message || body || 'Unknown error' };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=web-push.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-push.js","sourceRoot":"","sources":["../../src/push/web-push.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+CAA+C;AAC/C,+DAA+D;AAE/D,OAAO,OAAO,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAYzC,MAAM,OAAO,eAAe;IACjB,IAAI,GAAG,UAAU,CAAC;IAClB,cAAc,CAAS;IAEhC,YAAY,MAAqB;QAC/B,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;QAC5C,OAAO,CAAC,eAAe,CACrB,MAAM,CAAC,UAAU,EACjB,MAAM,CAAC,cAAc,EACrB,MAAM,CAAC,eAAe,CACvB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAa,EAAE,OAAoB;QAC5C,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAE3B,IAAI,YAAsC,CAAC;QAC3C,IAAI,CAAC;YACH,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,IAAI,CAAC,oCAAoC,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;YACvF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,2BAA2B,EAAE,CAAC;QAC5E,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC;YACjC,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;SAChD,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,gBAAgB,CAAC,YAAY,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;YACzE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,UAAU,GAAI,GAA+B,CAAC,UAAU,CAAC;YAC/D,MAAM,IAAI,GAAI,GAAyB,CAAC,IAAI,CAAC;YAC7C,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,GAAG,EAAE,CAAC;gBAC7C,MAAM,CAAC,IAAI,CAAC,+BAA+B,EAAE,EAAE,QAAQ,EAAE,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBAC9F,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC;YACvE,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE;gBAClC,MAAM,EAAE,UAAU;gBAClB,KAAK,EAAG,GAAa,CAAC,OAAO,IAAI,IAAI,IAAI,MAAM,CAAC,GAAG,CAAC;aACrD,CAAC,CAAC;YACH,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,IAAI,IAAI,IAAI,eAAe,EAAE,CAAC;QACtF,CAAC;IACH,CAAC;CACF"}
|
package/dist/server.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { WebSocket } from 'ws';
|
|
|
2
2
|
import type { Server } from 'http';
|
|
3
3
|
import { Storage } from './storage.js';
|
|
4
4
|
import type { AuthProvider } from './auth.js';
|
|
5
|
+
import type { PushManager } from './push/index.js';
|
|
5
6
|
export interface HeadServerOptions {
|
|
6
7
|
authProviders?: Map<string, AuthProvider>;
|
|
7
8
|
authProvider?: AuthProvider;
|
|
@@ -9,6 +10,7 @@ export interface HeadServerOptions {
|
|
|
9
10
|
pairingEnabled?: boolean;
|
|
10
11
|
pairingTtl?: number;
|
|
11
12
|
version?: string;
|
|
13
|
+
pushManager?: PushManager;
|
|
12
14
|
}
|
|
13
15
|
export declare class HeadServer {
|
|
14
16
|
private wss;
|
|
@@ -25,6 +27,7 @@ export declare class HeadServer {
|
|
|
25
27
|
private getAuthProvider;
|
|
26
28
|
private getAuthProviderForMode;
|
|
27
29
|
private getGitHubClientId;
|
|
30
|
+
private getVapidPublicKey;
|
|
28
31
|
private findGitHubProvider;
|
|
29
32
|
attach(server: Server): void;
|
|
30
33
|
acceptConnection(ws: WebSocket): void;
|
|
@@ -41,10 +44,14 @@ export declare class HeadServer {
|
|
|
41
44
|
private handleCreatePairingToken;
|
|
42
45
|
private handleRequestPairingToken;
|
|
43
46
|
private handleRemoveDevice;
|
|
47
|
+
private handleRegisterPushToken;
|
|
48
|
+
private handleUnregisterPushToken;
|
|
44
49
|
private broadcastDeviceRemoved;
|
|
45
50
|
private broadcastDeviceJoined;
|
|
46
51
|
private broadcastDeviceLeft;
|
|
47
52
|
private getDeviceSummaries;
|
|
48
53
|
private sendError;
|
|
54
|
+
/** Flush pending messages from SQLite, parse into envelope objects. */
|
|
55
|
+
private flushPendingEnvelopes;
|
|
49
56
|
close(): void;
|
|
50
57
|
}
|