@de-otio/chaoskb-server 0.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/dist/lib/admin-handler/index.d.ts +22 -0
- package/dist/lib/admin-handler/index.d.ts.map +1 -0
- package/dist/lib/admin-handler/index.js +92 -0
- package/dist/lib/admin-handler/index.js.map +1 -0
- package/dist/lib/admin-handler/index.ts +123 -0
- package/dist/lib/admin-handler/routes/metrics.d.ts +11 -0
- package/dist/lib/admin-handler/routes/metrics.d.ts.map +1 -0
- package/dist/lib/admin-handler/routes/metrics.js +200 -0
- package/dist/lib/admin-handler/routes/metrics.js.map +1 -0
- package/dist/lib/admin-handler/routes/metrics.ts +234 -0
- package/dist/lib/admin-handler/routes/overview.d.ts +9 -0
- package/dist/lib/admin-handler/routes/overview.d.ts.map +1 -0
- package/dist/lib/admin-handler/routes/overview.js +110 -0
- package/dist/lib/admin-handler/routes/overview.js.map +1 -0
- package/dist/lib/admin-handler/routes/overview.ts +133 -0
- package/dist/lib/admin-handler/routes/tenants.d.ts +10 -0
- package/dist/lib/admin-handler/routes/tenants.d.ts.map +1 -0
- package/dist/lib/admin-handler/routes/tenants.js +108 -0
- package/dist/lib/admin-handler/routes/tenants.js.map +1 -0
- package/dist/lib/admin-handler/routes/tenants.ts +134 -0
- package/dist/lib/chaoskb-stack.d.ts +22 -0
- package/dist/lib/chaoskb-stack.d.ts.map +1 -0
- package/dist/lib/chaoskb-stack.js +60 -0
- package/dist/lib/chaoskb-stack.js.map +1 -0
- package/dist/lib/constructs/admin-api.d.ts +16 -0
- package/dist/lib/constructs/admin-api.d.ts.map +1 -0
- package/dist/lib/constructs/admin-api.js +93 -0
- package/dist/lib/constructs/admin-api.js.map +1 -0
- package/dist/lib/constructs/admin-dashboard.d.ts +18 -0
- package/dist/lib/constructs/admin-dashboard.d.ts.map +1 -0
- package/dist/lib/constructs/admin-dashboard.js +172 -0
- package/dist/lib/constructs/admin-dashboard.js.map +1 -0
- package/dist/lib/constructs/api.d.ts +17 -0
- package/dist/lib/constructs/api.d.ts.map +1 -0
- package/dist/lib/constructs/api.js +81 -0
- package/dist/lib/constructs/api.js.map +1 -0
- package/dist/lib/constructs/auth.d.ts +11 -0
- package/dist/lib/constructs/auth.d.ts.map +1 -0
- package/dist/lib/constructs/auth.js +18 -0
- package/dist/lib/constructs/auth.js.map +1 -0
- package/dist/lib/constructs/blob-store.d.ts +10 -0
- package/dist/lib/constructs/blob-store.d.ts.map +1 -0
- package/dist/lib/constructs/blob-store.js +31 -0
- package/dist/lib/constructs/blob-store.js.map +1 -0
- package/dist/lib/deploy-cli.d.ts +3 -0
- package/dist/lib/deploy-cli.d.ts.map +1 -0
- package/dist/lib/deploy-cli.js +49 -0
- package/dist/lib/deploy-cli.js.map +1 -0
- package/dist/lib/handler/index.d.ts +23 -0
- package/dist/lib/handler/index.d.ts.map +1 -0
- package/dist/lib/handler/index.js +276 -0
- package/dist/lib/handler/index.js.map +1 -0
- package/dist/lib/handler/index.ts +372 -0
- package/dist/lib/handler/logger.d.ts +16 -0
- package/dist/lib/handler/logger.d.ts.map +1 -0
- package/dist/lib/handler/logger.js +26 -0
- package/dist/lib/handler/logger.js.map +1 -0
- package/dist/lib/handler/logger.ts +36 -0
- package/dist/lib/handler/middleware/input-validation.d.ts +6 -0
- package/dist/lib/handler/middleware/input-validation.d.ts.map +1 -0
- package/dist/lib/handler/middleware/input-validation.js +36 -0
- package/dist/lib/handler/middleware/input-validation.js.map +1 -0
- package/dist/lib/handler/middleware/input-validation.ts +44 -0
- package/dist/lib/handler/middleware/rate-limit.d.ts +14 -0
- package/dist/lib/handler/middleware/rate-limit.d.ts.map +1 -0
- package/dist/lib/handler/middleware/rate-limit.js +94 -0
- package/dist/lib/handler/middleware/rate-limit.js.map +1 -0
- package/dist/lib/handler/middleware/rate-limit.ts +121 -0
- package/dist/lib/handler/middleware/ssh-auth.d.ts +48 -0
- package/dist/lib/handler/middleware/ssh-auth.d.ts.map +1 -0
- package/dist/lib/handler/middleware/ssh-auth.js +256 -0
- package/dist/lib/handler/middleware/ssh-auth.js.map +1 -0
- package/dist/lib/handler/middleware/ssh-auth.ts +300 -0
- package/dist/lib/handler/routes/audit.d.ts +24 -0
- package/dist/lib/handler/routes/audit.d.ts.map +1 -0
- package/dist/lib/handler/routes/audit.js +94 -0
- package/dist/lib/handler/routes/audit.js.map +1 -0
- package/dist/lib/handler/routes/audit.ts +101 -0
- package/dist/lib/handler/routes/blobs.d.ts +13 -0
- package/dist/lib/handler/routes/blobs.d.ts.map +1 -0
- package/dist/lib/handler/routes/blobs.js +298 -0
- package/dist/lib/handler/routes/blobs.js.map +1 -0
- package/dist/lib/handler/routes/blobs.ts +348 -0
- package/dist/lib/handler/routes/devices.d.ts +48 -0
- package/dist/lib/handler/routes/devices.d.ts.map +1 -0
- package/dist/lib/handler/routes/devices.js +394 -0
- package/dist/lib/handler/routes/devices.js.map +1 -0
- package/dist/lib/handler/routes/devices.ts +458 -0
- package/dist/lib/handler/routes/export.d.ts +9 -0
- package/dist/lib/handler/routes/export.d.ts.map +1 -0
- package/dist/lib/handler/routes/export.js +40 -0
- package/dist/lib/handler/routes/export.js.map +1 -0
- package/dist/lib/handler/routes/export.ts +55 -0
- package/dist/lib/handler/routes/github.d.ts +31 -0
- package/dist/lib/handler/routes/github.d.ts.map +1 -0
- package/dist/lib/handler/routes/github.js +118 -0
- package/dist/lib/handler/routes/github.js.map +1 -0
- package/dist/lib/handler/routes/github.ts +162 -0
- package/dist/lib/handler/routes/health.d.ts +6 -0
- package/dist/lib/handler/routes/health.d.ts.map +1 -0
- package/dist/lib/handler/routes/health.js +14 -0
- package/dist/lib/handler/routes/health.js.map +1 -0
- package/dist/lib/handler/routes/health.ts +10 -0
- package/dist/lib/handler/routes/invites.d.ts +24 -0
- package/dist/lib/handler/routes/invites.d.ts.map +1 -0
- package/dist/lib/handler/routes/invites.js +445 -0
- package/dist/lib/handler/routes/invites.js.map +1 -0
- package/dist/lib/handler/routes/invites.ts +527 -0
- package/dist/lib/handler/routes/notifications.d.ts +39 -0
- package/dist/lib/handler/routes/notifications.d.ts.map +1 -0
- package/dist/lib/handler/routes/notifications.js +150 -0
- package/dist/lib/handler/routes/notifications.js.map +1 -0
- package/dist/lib/handler/routes/notifications.ts +163 -0
- package/dist/lib/handler/routes/projects.d.ts +24 -0
- package/dist/lib/handler/routes/projects.d.ts.map +1 -0
- package/dist/lib/handler/routes/projects.js +47 -0
- package/dist/lib/handler/routes/projects.js.map +1 -0
- package/dist/lib/handler/routes/projects.ts +69 -0
- package/dist/lib/handler/routes/register.d.ts +19 -0
- package/dist/lib/handler/routes/register.d.ts.map +1 -0
- package/dist/lib/handler/routes/register.js +327 -0
- package/dist/lib/handler/routes/register.js.map +1 -0
- package/dist/lib/handler/routes/register.ts +363 -0
- package/dist/lib/handler/routes/restore.d.ts +9 -0
- package/dist/lib/handler/routes/restore.d.ts.map +1 -0
- package/dist/lib/handler/routes/restore.js +52 -0
- package/dist/lib/handler/routes/restore.js.map +1 -0
- package/dist/lib/handler/routes/restore.ts +73 -0
- package/dist/lib/handler/routes/revocation.d.ts +13 -0
- package/dist/lib/handler/routes/revocation.d.ts.map +1 -0
- package/dist/lib/handler/routes/revocation.js +63 -0
- package/dist/lib/handler/routes/revocation.js.map +1 -0
- package/dist/lib/handler/routes/revocation.ts +87 -0
- package/dist/lib/handler/routes/rotation.d.ts +24 -0
- package/dist/lib/handler/routes/rotation.d.ts.map +1 -0
- package/dist/lib/handler/routes/rotation.js +291 -0
- package/dist/lib/handler/routes/rotation.js.map +1 -0
- package/dist/lib/handler/routes/rotation.ts +336 -0
- package/dist/lib/handler/routes/tenants.d.ts +11 -0
- package/dist/lib/handler/routes/tenants.d.ts.map +1 -0
- package/dist/lib/handler/routes/tenants.js +181 -0
- package/dist/lib/handler/routes/tenants.js.map +1 -0
- package/dist/lib/handler/routes/tenants.ts +198 -0
- package/dist/lib/handler/routes/wrapped-key.d.ts +21 -0
- package/dist/lib/handler/routes/wrapped-key.d.ts.map +1 -0
- package/dist/lib/handler/routes/wrapped-key.js +76 -0
- package/dist/lib/handler/routes/wrapped-key.js.map +1 -0
- package/dist/lib/handler/routes/wrapped-key.ts +108 -0
- package/dist/lib/index.d.ts +7 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +16 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/vitest.config.js +18 -0
- package/dist/vitest.config.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
|
|
2
|
+
interface HandlerResponse {
|
|
3
|
+
statusCode: number;
|
|
4
|
+
body: string;
|
|
5
|
+
headers: Record<string, string>;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* POST /v1/link-code — authenticated
|
|
9
|
+
*
|
|
10
|
+
* Creates a link code record so a new device can join this tenant.
|
|
11
|
+
* The caller displays the raw code; the server stores only its SHA-256 hash.
|
|
12
|
+
*/
|
|
13
|
+
export declare function handleCreateLinkCode(tenantId: string, body: string | null | undefined, ddb: DynamoDBDocumentClient, tableName: string): Promise<HandlerResponse>;
|
|
14
|
+
/**
|
|
15
|
+
* POST /v1/link-confirm — unauthenticated (new device)
|
|
16
|
+
*
|
|
17
|
+
* The new device sends the raw link code and its public key.
|
|
18
|
+
* We hash the code, look up the LINK record, validate expiry and failure count,
|
|
19
|
+
* and store the public key for the existing device to pick up.
|
|
20
|
+
*/
|
|
21
|
+
export declare function handleLinkConfirm(body: string | null | undefined, ddb: DynamoDBDocumentClient, tableName: string): Promise<HandlerResponse>;
|
|
22
|
+
/**
|
|
23
|
+
* POST /v1/link-code (extended) — also writes the reverse-lookup record.
|
|
24
|
+
*
|
|
25
|
+
* This is a wrapper that ensures both the tenant-scoped LINK# record
|
|
26
|
+
* and the top-level LINK_CODE# lookup record are created.
|
|
27
|
+
*/
|
|
28
|
+
export declare function handleCreateLinkCodeFull(tenantId: string, body: string | null | undefined, ddb: DynamoDBDocumentClient, tableName: string): Promise<HandlerResponse>;
|
|
29
|
+
/**
|
|
30
|
+
* GET /v1/link-code/{hash}/status — authenticated
|
|
31
|
+
*
|
|
32
|
+
* Returns { status: 'waiting' } or { status: 'ready', newPublicKey }.
|
|
33
|
+
*/
|
|
34
|
+
export declare function handleGetLinkCodeStatus(tenantId: string, codeHash: string, ddb: DynamoDBDocumentClient, tableName: string): Promise<HandlerResponse>;
|
|
35
|
+
/**
|
|
36
|
+
* GET /v1/devices — authenticated
|
|
37
|
+
*
|
|
38
|
+
* Lists all registered devices (KEY#{fingerprint} items) for the tenant.
|
|
39
|
+
*/
|
|
40
|
+
export declare function handleListDevices(tenantId: string, ddb: DynamoDBDocumentClient, tableName: string): Promise<HandlerResponse>;
|
|
41
|
+
/**
|
|
42
|
+
* DELETE /v1/devices/{fingerprint} — authenticated
|
|
43
|
+
*
|
|
44
|
+
* Removes the KEY# item and WRAPPED_KEY# item for the given device.
|
|
45
|
+
*/
|
|
46
|
+
export declare function handleDeleteDevice(tenantId: string, fingerprint: string, ddb: DynamoDBDocumentClient, tableName: string): Promise<HandlerResponse>;
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=devices.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devices.d.ts","sourceRoot":"","sources":["../../../../lib/handler/routes/devices.ts"],"names":[],"mappings":"AACA,OAAO,EACL,sBAAsB,EAMvB,MAAM,uBAAuB,CAAC;AAI/B,UAAU,eAAe;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAID;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,GAAG,EAAE,sBAAsB,EAC3B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAqD1B;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,GAAG,EAAE,sBAAsB,EAC3B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAwJ1B;AAED;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,GAAG,EAAE,sBAAsB,EAC3B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAoE1B;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,sBAAsB,EAC3B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAkC1B;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,sBAAsB,EAC3B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAuB1B;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,sBAAsB,EAC3B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAmC1B"}
|
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.handleCreateLinkCode = handleCreateLinkCode;
|
|
37
|
+
exports.handleLinkConfirm = handleLinkConfirm;
|
|
38
|
+
exports.handleCreateLinkCodeFull = handleCreateLinkCodeFull;
|
|
39
|
+
exports.handleGetLinkCodeStatus = handleGetLinkCodeStatus;
|
|
40
|
+
exports.handleListDevices = handleListDevices;
|
|
41
|
+
exports.handleDeleteDevice = handleDeleteDevice;
|
|
42
|
+
const crypto = __importStar(require("crypto"));
|
|
43
|
+
const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
|
|
44
|
+
const logger_js_1 = require("../logger.js");
|
|
45
|
+
const notifications_js_1 = require("./notifications.js");
|
|
46
|
+
const JSON_HEADERS = { 'Content-Type': 'application/json' };
|
|
47
|
+
/**
|
|
48
|
+
* POST /v1/link-code — authenticated
|
|
49
|
+
*
|
|
50
|
+
* Creates a link code record so a new device can join this tenant.
|
|
51
|
+
* The caller displays the raw code; the server stores only its SHA-256 hash.
|
|
52
|
+
*/
|
|
53
|
+
async function handleCreateLinkCode(tenantId, body, ddb, tableName) {
|
|
54
|
+
if (!body) {
|
|
55
|
+
return {
|
|
56
|
+
statusCode: 400,
|
|
57
|
+
headers: JSON_HEADERS,
|
|
58
|
+
body: JSON.stringify({ error: 'invalid_request', message: 'Request body is required' }),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
let parsed;
|
|
62
|
+
try {
|
|
63
|
+
parsed = JSON.parse(body);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return {
|
|
67
|
+
statusCode: 400,
|
|
68
|
+
headers: JSON_HEADERS,
|
|
69
|
+
body: JSON.stringify({ error: 'invalid_request', message: 'Invalid JSON body' }),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (!parsed.codeHash || typeof parsed.codeHash !== 'string') {
|
|
73
|
+
return {
|
|
74
|
+
statusCode: 400,
|
|
75
|
+
headers: JSON_HEADERS,
|
|
76
|
+
body: JSON.stringify({ error: 'invalid_request', message: 'codeHash is required' }),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const now = new Date();
|
|
80
|
+
const expiresAt = new Date(now.getTime() + 5 * 60 * 1000).toISOString();
|
|
81
|
+
const ttl = Math.floor(now.getTime() / 1000) + 10 * 60; // DynamoDB TTL: 10 min (generous)
|
|
82
|
+
await ddb.send(new lib_dynamodb_1.PutCommand({
|
|
83
|
+
TableName: tableName,
|
|
84
|
+
Item: {
|
|
85
|
+
PK: `TENANT#${tenantId}`,
|
|
86
|
+
SK: `LINK#${parsed.codeHash}`,
|
|
87
|
+
newPublicKey: null,
|
|
88
|
+
failureCount: 0,
|
|
89
|
+
expiresAt,
|
|
90
|
+
ttl,
|
|
91
|
+
},
|
|
92
|
+
}));
|
|
93
|
+
logger_js_1.logger.info('Link code created', { tenantId });
|
|
94
|
+
return {
|
|
95
|
+
statusCode: 201,
|
|
96
|
+
headers: JSON_HEADERS,
|
|
97
|
+
body: JSON.stringify({ status: 'created', expiresAt }),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* POST /v1/link-confirm — unauthenticated (new device)
|
|
102
|
+
*
|
|
103
|
+
* The new device sends the raw link code and its public key.
|
|
104
|
+
* We hash the code, look up the LINK record, validate expiry and failure count,
|
|
105
|
+
* and store the public key for the existing device to pick up.
|
|
106
|
+
*/
|
|
107
|
+
async function handleLinkConfirm(body, ddb, tableName) {
|
|
108
|
+
if (!body) {
|
|
109
|
+
return {
|
|
110
|
+
statusCode: 400,
|
|
111
|
+
headers: JSON_HEADERS,
|
|
112
|
+
body: JSON.stringify({ error: 'invalid_request', message: 'Request body is required' }),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
let parsed;
|
|
116
|
+
try {
|
|
117
|
+
parsed = JSON.parse(body);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return {
|
|
121
|
+
statusCode: 400,
|
|
122
|
+
headers: JSON_HEADERS,
|
|
123
|
+
body: JSON.stringify({ error: 'invalid_request', message: 'Invalid JSON body' }),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
if (!parsed.linkCode || !parsed.publicKey) {
|
|
127
|
+
return {
|
|
128
|
+
statusCode: 400,
|
|
129
|
+
headers: JSON_HEADERS,
|
|
130
|
+
body: JSON.stringify({ error: 'invalid_request', message: 'linkCode and publicKey are required' }),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
const codeHash = crypto.createHash('sha256').update(parsed.linkCode).digest('hex');
|
|
134
|
+
// Find the LINK record across tenants — query by SK pattern
|
|
135
|
+
// We need to scan for the link code. Since link codes are short-lived and rare,
|
|
136
|
+
// we use a GSI or scan. For simplicity, the caller must provide tenantId or
|
|
137
|
+
// we search by a known pattern. Actually, the link code hash is unique enough
|
|
138
|
+
// that we store a reverse-lookup record.
|
|
139
|
+
//
|
|
140
|
+
// Alternative approach: query all tenants. But DynamoDB doesn't support that
|
|
141
|
+
// efficiently. Instead, store a top-level LINK_CODE#{hash} -> tenantId mapping.
|
|
142
|
+
//
|
|
143
|
+
// For this implementation, the link-confirm looks up LINK_CODE#{hash} at the
|
|
144
|
+
// table level (PK = LINK_CODE#{hash}).
|
|
145
|
+
const lookupResult = await ddb.send(new lib_dynamodb_1.GetCommand({
|
|
146
|
+
TableName: tableName,
|
|
147
|
+
Key: {
|
|
148
|
+
PK: `LINK_CODE#${codeHash}`,
|
|
149
|
+
SK: 'META',
|
|
150
|
+
},
|
|
151
|
+
}));
|
|
152
|
+
// Fallback: try the tenant-scoped approach by scanning LINK# records
|
|
153
|
+
// For the initial implementation, we use a top-level lookup key.
|
|
154
|
+
// The handleCreateLinkCode also writes this lookup record.
|
|
155
|
+
if (!lookupResult.Item) {
|
|
156
|
+
return {
|
|
157
|
+
statusCode: 404,
|
|
158
|
+
headers: JSON_HEADERS,
|
|
159
|
+
body: JSON.stringify({ error: 'not_found', message: 'Invalid or expired link code' }),
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
const tenantId = lookupResult.Item['tenantId'];
|
|
163
|
+
// Fetch the tenant-scoped link record
|
|
164
|
+
const linkResult = await ddb.send(new lib_dynamodb_1.GetCommand({
|
|
165
|
+
TableName: tableName,
|
|
166
|
+
Key: {
|
|
167
|
+
PK: `TENANT#${tenantId}`,
|
|
168
|
+
SK: `LINK#${codeHash}`,
|
|
169
|
+
},
|
|
170
|
+
}));
|
|
171
|
+
if (!linkResult.Item) {
|
|
172
|
+
return {
|
|
173
|
+
statusCode: 404,
|
|
174
|
+
headers: JSON_HEADERS,
|
|
175
|
+
body: JSON.stringify({ error: 'not_found', message: 'Invalid or expired link code' }),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
const linkRecord = linkResult.Item;
|
|
179
|
+
// Check expiry
|
|
180
|
+
if (new Date(linkRecord['expiresAt']) < new Date()) {
|
|
181
|
+
return {
|
|
182
|
+
statusCode: 410,
|
|
183
|
+
headers: JSON_HEADERS,
|
|
184
|
+
body: JSON.stringify({ error: 'expired', message: 'Link code has expired' }),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
// Check failure count
|
|
188
|
+
const failureCount = linkRecord['failureCount'] ?? 0;
|
|
189
|
+
if (failureCount >= 3) {
|
|
190
|
+
// Delete the record
|
|
191
|
+
await ddb.send(new lib_dynamodb_1.DeleteCommand({
|
|
192
|
+
TableName: tableName,
|
|
193
|
+
Key: { PK: `TENANT#${tenantId}`, SK: `LINK#${codeHash}` },
|
|
194
|
+
}));
|
|
195
|
+
await ddb.send(new lib_dynamodb_1.DeleteCommand({
|
|
196
|
+
TableName: tableName,
|
|
197
|
+
Key: { PK: `LINK_CODE#${codeHash}`, SK: 'META' },
|
|
198
|
+
}));
|
|
199
|
+
return {
|
|
200
|
+
statusCode: 429,
|
|
201
|
+
headers: JSON_HEADERS,
|
|
202
|
+
body: JSON.stringify({ error: 'too_many_failures', message: 'Too many failed attempts' }),
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
// Store the new device's public key in the link record
|
|
206
|
+
try {
|
|
207
|
+
await ddb.send(new lib_dynamodb_1.UpdateCommand({
|
|
208
|
+
TableName: tableName,
|
|
209
|
+
Key: {
|
|
210
|
+
PK: `TENANT#${tenantId}`,
|
|
211
|
+
SK: `LINK#${codeHash}`,
|
|
212
|
+
},
|
|
213
|
+
UpdateExpression: 'SET newPublicKey = :pk',
|
|
214
|
+
ConditionExpression: 'attribute_exists(PK)',
|
|
215
|
+
ExpressionAttributeValues: {
|
|
216
|
+
':pk': parsed.publicKey,
|
|
217
|
+
},
|
|
218
|
+
}));
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
if (err.name === 'ConditionalCheckFailedException') {
|
|
222
|
+
return {
|
|
223
|
+
statusCode: 404,
|
|
224
|
+
headers: JSON_HEADERS,
|
|
225
|
+
body: JSON.stringify({ error: 'not_found', message: 'Link code no longer valid' }),
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
throw err;
|
|
229
|
+
}
|
|
230
|
+
logger_js_1.logger.info('Link confirmed', { tenantId, codeHash: codeHash.slice(0, 8) });
|
|
231
|
+
return {
|
|
232
|
+
statusCode: 200,
|
|
233
|
+
headers: JSON_HEADERS,
|
|
234
|
+
body: JSON.stringify({ status: 'confirmed' }),
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* POST /v1/link-code (extended) — also writes the reverse-lookup record.
|
|
239
|
+
*
|
|
240
|
+
* This is a wrapper that ensures both the tenant-scoped LINK# record
|
|
241
|
+
* and the top-level LINK_CODE# lookup record are created.
|
|
242
|
+
*/
|
|
243
|
+
async function handleCreateLinkCodeFull(tenantId, body, ddb, tableName) {
|
|
244
|
+
if (!body) {
|
|
245
|
+
return {
|
|
246
|
+
statusCode: 400,
|
|
247
|
+
headers: JSON_HEADERS,
|
|
248
|
+
body: JSON.stringify({ error: 'invalid_request', message: 'Request body is required' }),
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
let parsed;
|
|
252
|
+
try {
|
|
253
|
+
parsed = JSON.parse(body);
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
return {
|
|
257
|
+
statusCode: 400,
|
|
258
|
+
headers: JSON_HEADERS,
|
|
259
|
+
body: JSON.stringify({ error: 'invalid_request', message: 'Invalid JSON body' }),
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
if (!parsed.codeHash || typeof parsed.codeHash !== 'string') {
|
|
263
|
+
return {
|
|
264
|
+
statusCode: 400,
|
|
265
|
+
headers: JSON_HEADERS,
|
|
266
|
+
body: JSON.stringify({ error: 'invalid_request', message: 'codeHash is required' }),
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
const now = new Date();
|
|
270
|
+
const expiresAt = new Date(now.getTime() + 5 * 60 * 1000).toISOString();
|
|
271
|
+
const ttl = Math.floor(now.getTime() / 1000) + 10 * 60;
|
|
272
|
+
// Write the tenant-scoped link record
|
|
273
|
+
await ddb.send(new lib_dynamodb_1.PutCommand({
|
|
274
|
+
TableName: tableName,
|
|
275
|
+
Item: {
|
|
276
|
+
PK: `TENANT#${tenantId}`,
|
|
277
|
+
SK: `LINK#${parsed.codeHash}`,
|
|
278
|
+
newPublicKey: null,
|
|
279
|
+
failureCount: 0,
|
|
280
|
+
expiresAt,
|
|
281
|
+
ttl,
|
|
282
|
+
},
|
|
283
|
+
}));
|
|
284
|
+
// Write the reverse-lookup record (for unauthenticated link-confirm)
|
|
285
|
+
await ddb.send(new lib_dynamodb_1.PutCommand({
|
|
286
|
+
TableName: tableName,
|
|
287
|
+
Item: {
|
|
288
|
+
PK: `LINK_CODE#${parsed.codeHash}`,
|
|
289
|
+
SK: 'META',
|
|
290
|
+
tenantId,
|
|
291
|
+
expiresAt,
|
|
292
|
+
ttl,
|
|
293
|
+
},
|
|
294
|
+
}));
|
|
295
|
+
logger_js_1.logger.info('Link code created', { tenantId });
|
|
296
|
+
return {
|
|
297
|
+
statusCode: 201,
|
|
298
|
+
headers: JSON_HEADERS,
|
|
299
|
+
body: JSON.stringify({ status: 'created', expiresAt }),
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* GET /v1/link-code/{hash}/status — authenticated
|
|
304
|
+
*
|
|
305
|
+
* Returns { status: 'waiting' } or { status: 'ready', newPublicKey }.
|
|
306
|
+
*/
|
|
307
|
+
async function handleGetLinkCodeStatus(tenantId, codeHash, ddb, tableName) {
|
|
308
|
+
const result = await ddb.send(new lib_dynamodb_1.GetCommand({
|
|
309
|
+
TableName: tableName,
|
|
310
|
+
Key: {
|
|
311
|
+
PK: `TENANT#${tenantId}`,
|
|
312
|
+
SK: `LINK#${codeHash}`,
|
|
313
|
+
},
|
|
314
|
+
}));
|
|
315
|
+
if (!result.Item) {
|
|
316
|
+
return {
|
|
317
|
+
statusCode: 404,
|
|
318
|
+
headers: JSON_HEADERS,
|
|
319
|
+
body: JSON.stringify({ error: 'not_found', message: 'Link code not found' }),
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
const newPublicKey = result.Item['newPublicKey'];
|
|
323
|
+
if (newPublicKey) {
|
|
324
|
+
return {
|
|
325
|
+
statusCode: 200,
|
|
326
|
+
headers: JSON_HEADERS,
|
|
327
|
+
body: JSON.stringify({ status: 'ready', newPublicKey }),
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
statusCode: 200,
|
|
332
|
+
headers: JSON_HEADERS,
|
|
333
|
+
body: JSON.stringify({ status: 'waiting' }),
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* GET /v1/devices — authenticated
|
|
338
|
+
*
|
|
339
|
+
* Lists all registered devices (KEY#{fingerprint} items) for the tenant.
|
|
340
|
+
*/
|
|
341
|
+
async function handleListDevices(tenantId, ddb, tableName) {
|
|
342
|
+
const result = await ddb.send(new lib_dynamodb_1.QueryCommand({
|
|
343
|
+
TableName: tableName,
|
|
344
|
+
KeyConditionExpression: 'PK = :pk AND begins_with(SK, :prefix)',
|
|
345
|
+
ExpressionAttributeValues: {
|
|
346
|
+
':pk': `TENANT#${tenantId}`,
|
|
347
|
+
':prefix': 'KEY#',
|
|
348
|
+
},
|
|
349
|
+
}));
|
|
350
|
+
const devices = (result.Items ?? []).map((item) => ({
|
|
351
|
+
fingerprint: item['SK'].replace('KEY#', ''),
|
|
352
|
+
registeredAt: item['registeredAt'],
|
|
353
|
+
publicKey: item['publicKey'],
|
|
354
|
+
}));
|
|
355
|
+
return {
|
|
356
|
+
statusCode: 200,
|
|
357
|
+
headers: JSON_HEADERS,
|
|
358
|
+
body: JSON.stringify({ devices }),
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* DELETE /v1/devices/{fingerprint} — authenticated
|
|
363
|
+
*
|
|
364
|
+
* Removes the KEY# item and WRAPPED_KEY# item for the given device.
|
|
365
|
+
*/
|
|
366
|
+
async function handleDeleteDevice(tenantId, fingerprint, ddb, tableName) {
|
|
367
|
+
// Delete the KEY# record
|
|
368
|
+
await ddb.send(new lib_dynamodb_1.DeleteCommand({
|
|
369
|
+
TableName: tableName,
|
|
370
|
+
Key: {
|
|
371
|
+
PK: `TENANT#${tenantId}`,
|
|
372
|
+
SK: `KEY#${fingerprint}`,
|
|
373
|
+
},
|
|
374
|
+
}));
|
|
375
|
+
// Delete the WRAPPED_KEY# record
|
|
376
|
+
await ddb.send(new lib_dynamodb_1.DeleteCommand({
|
|
377
|
+
TableName: tableName,
|
|
378
|
+
Key: {
|
|
379
|
+
PK: `TENANT#${tenantId}`,
|
|
380
|
+
SK: `WRAPPED_KEY#${fingerprint}`,
|
|
381
|
+
},
|
|
382
|
+
}));
|
|
383
|
+
// Create revocation notification for remaining devices
|
|
384
|
+
await (0, notifications_js_1.createNotification)(tenantId, 'device_revoked', {
|
|
385
|
+
hostname: fingerprint,
|
|
386
|
+
}, ddb, tableName);
|
|
387
|
+
logger_js_1.logger.info('Device removed', { tenantId, fingerprint });
|
|
388
|
+
return {
|
|
389
|
+
statusCode: 200,
|
|
390
|
+
headers: JSON_HEADERS,
|
|
391
|
+
body: JSON.stringify({ status: 'deleted' }),
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
//# sourceMappingURL=devices.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devices.js","sourceRoot":"","sources":["../../../../lib/handler/routes/devices.ts"],"names":[],"mappings":"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"}
|