harper-kb 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.
Files changed (146) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +288 -0
  3. package/config.yaml +13 -0
  4. package/dist/core/embeddings.d.ts +31 -0
  5. package/dist/core/embeddings.d.ts.map +1 -0
  6. package/dist/core/embeddings.js +199 -0
  7. package/dist/core/embeddings.js.map +1 -0
  8. package/dist/core/entries.d.ts +101 -0
  9. package/dist/core/entries.d.ts.map +1 -0
  10. package/dist/core/entries.js +304 -0
  11. package/dist/core/entries.js.map +1 -0
  12. package/dist/core/history.d.ts +31 -0
  13. package/dist/core/history.d.ts.map +1 -0
  14. package/dist/core/history.js +119 -0
  15. package/dist/core/history.js.map +1 -0
  16. package/dist/core/knowledge-base.d.ts +49 -0
  17. package/dist/core/knowledge-base.d.ts.map +1 -0
  18. package/dist/core/knowledge-base.js +117 -0
  19. package/dist/core/knowledge-base.js.map +1 -0
  20. package/dist/core/search.d.ts +34 -0
  21. package/dist/core/search.d.ts.map +1 -0
  22. package/dist/core/search.js +327 -0
  23. package/dist/core/search.js.map +1 -0
  24. package/dist/core/tags.d.ts +39 -0
  25. package/dist/core/tags.d.ts.map +1 -0
  26. package/dist/core/tags.js +97 -0
  27. package/dist/core/tags.js.map +1 -0
  28. package/dist/core/triage.d.ts +61 -0
  29. package/dist/core/triage.d.ts.map +1 -0
  30. package/dist/core/triage.js +136 -0
  31. package/dist/core/triage.js.map +1 -0
  32. package/dist/core/webhook-endpoints.d.ts +46 -0
  33. package/dist/core/webhook-endpoints.d.ts.map +1 -0
  34. package/dist/core/webhook-endpoints.js +85 -0
  35. package/dist/core/webhook-endpoints.js.map +1 -0
  36. package/dist/hooks.d.ts +67 -0
  37. package/dist/hooks.d.ts.map +1 -0
  38. package/dist/hooks.js +53 -0
  39. package/dist/hooks.js.map +1 -0
  40. package/dist/http-utils.d.ts +38 -0
  41. package/dist/http-utils.d.ts.map +1 -0
  42. package/dist/http-utils.js +133 -0
  43. package/dist/http-utils.js.map +1 -0
  44. package/dist/index.d.ts +27 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +78 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/mcp/protocol.d.ts +25 -0
  49. package/dist/mcp/protocol.d.ts.map +1 -0
  50. package/dist/mcp/protocol.js +105 -0
  51. package/dist/mcp/protocol.js.map +1 -0
  52. package/dist/mcp/server.d.ts +28 -0
  53. package/dist/mcp/server.d.ts.map +1 -0
  54. package/dist/mcp/server.js +144 -0
  55. package/dist/mcp/server.js.map +1 -0
  56. package/dist/mcp/tools.d.ts +26 -0
  57. package/dist/mcp/tools.d.ts.map +1 -0
  58. package/dist/mcp/tools.js +706 -0
  59. package/dist/mcp/tools.js.map +1 -0
  60. package/dist/oauth/authorize.d.ts +28 -0
  61. package/dist/oauth/authorize.d.ts.map +1 -0
  62. package/dist/oauth/authorize.js +421 -0
  63. package/dist/oauth/authorize.js.map +1 -0
  64. package/dist/oauth/init.d.ts +18 -0
  65. package/dist/oauth/init.d.ts.map +1 -0
  66. package/dist/oauth/init.js +30 -0
  67. package/dist/oauth/init.js.map +1 -0
  68. package/dist/oauth/keys.d.ts +34 -0
  69. package/dist/oauth/keys.d.ts.map +1 -0
  70. package/dist/oauth/keys.js +101 -0
  71. package/dist/oauth/keys.js.map +1 -0
  72. package/dist/oauth/metadata.d.ts +23 -0
  73. package/dist/oauth/metadata.d.ts.map +1 -0
  74. package/dist/oauth/metadata.js +57 -0
  75. package/dist/oauth/metadata.js.map +1 -0
  76. package/dist/oauth/middleware.d.ts +23 -0
  77. package/dist/oauth/middleware.d.ts.map +1 -0
  78. package/dist/oauth/middleware.js +65 -0
  79. package/dist/oauth/middleware.js.map +1 -0
  80. package/dist/oauth/register.d.ts +15 -0
  81. package/dist/oauth/register.d.ts.map +1 -0
  82. package/dist/oauth/register.js +78 -0
  83. package/dist/oauth/register.js.map +1 -0
  84. package/dist/oauth/token.d.ts +16 -0
  85. package/dist/oauth/token.d.ts.map +1 -0
  86. package/dist/oauth/token.js +184 -0
  87. package/dist/oauth/token.js.map +1 -0
  88. package/dist/oauth/validate.d.ts +40 -0
  89. package/dist/oauth/validate.d.ts.map +1 -0
  90. package/dist/oauth/validate.js +61 -0
  91. package/dist/oauth/validate.js.map +1 -0
  92. package/dist/resources/HistoryResource.d.ts +41 -0
  93. package/dist/resources/HistoryResource.d.ts.map +1 -0
  94. package/dist/resources/HistoryResource.js +61 -0
  95. package/dist/resources/HistoryResource.js.map +1 -0
  96. package/dist/resources/KnowledgeBaseResource.d.ts +60 -0
  97. package/dist/resources/KnowledgeBaseResource.d.ts.map +1 -0
  98. package/dist/resources/KnowledgeBaseResource.js +118 -0
  99. package/dist/resources/KnowledgeBaseResource.js.map +1 -0
  100. package/dist/resources/KnowledgeEntryResource.d.ts +61 -0
  101. package/dist/resources/KnowledgeEntryResource.d.ts.map +1 -0
  102. package/dist/resources/KnowledgeEntryResource.js +191 -0
  103. package/dist/resources/KnowledgeEntryResource.js.map +1 -0
  104. package/dist/resources/MeResource.d.ts +31 -0
  105. package/dist/resources/MeResource.d.ts.map +1 -0
  106. package/dist/resources/MeResource.js +40 -0
  107. package/dist/resources/MeResource.js.map +1 -0
  108. package/dist/resources/QueryLogResource.d.ts +22 -0
  109. package/dist/resources/QueryLogResource.d.ts.map +1 -0
  110. package/dist/resources/QueryLogResource.js +66 -0
  111. package/dist/resources/QueryLogResource.js.map +1 -0
  112. package/dist/resources/ServiceKeyResource.d.ts +52 -0
  113. package/dist/resources/ServiceKeyResource.d.ts.map +1 -0
  114. package/dist/resources/ServiceKeyResource.js +151 -0
  115. package/dist/resources/ServiceKeyResource.js.map +1 -0
  116. package/dist/resources/TagResource.d.ts +27 -0
  117. package/dist/resources/TagResource.d.ts.map +1 -0
  118. package/dist/resources/TagResource.js +41 -0
  119. package/dist/resources/TagResource.js.map +1 -0
  120. package/dist/resources/TriageResource.d.ts +53 -0
  121. package/dist/resources/TriageResource.d.ts.map +1 -0
  122. package/dist/resources/TriageResource.js +120 -0
  123. package/dist/resources/TriageResource.js.map +1 -0
  124. package/dist/resources/WebhookEndpointResource.d.ts +63 -0
  125. package/dist/resources/WebhookEndpointResource.d.ts.map +1 -0
  126. package/dist/resources/WebhookEndpointResource.js +115 -0
  127. package/dist/resources/WebhookEndpointResource.js.map +1 -0
  128. package/dist/types.d.ts +378 -0
  129. package/dist/types.d.ts.map +1 -0
  130. package/dist/types.js +8 -0
  131. package/dist/types.js.map +1 -0
  132. package/dist/webhooks/github.d.ts +25 -0
  133. package/dist/webhooks/github.d.ts.map +1 -0
  134. package/dist/webhooks/github.js +165 -0
  135. package/dist/webhooks/github.js.map +1 -0
  136. package/dist/webhooks/middleware.d.ts +19 -0
  137. package/dist/webhooks/middleware.d.ts.map +1 -0
  138. package/dist/webhooks/middleware.js +144 -0
  139. package/dist/webhooks/middleware.js.map +1 -0
  140. package/dist/webhooks/types.d.ts +18 -0
  141. package/dist/webhooks/types.d.ts.map +1 -0
  142. package/dist/webhooks/types.js +5 -0
  143. package/dist/webhooks/types.js.map +1 -0
  144. package/package.json +69 -0
  145. package/schema/knowledge.graphql +136 -0
  146. package/schema/oauth.graphql +45 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * harper-kb — Type Definitions
3
+ *
4
+ * TypeScript interfaces for all table records, search parameters,
5
+ * and Harper global type declarations.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * GitHub Webhook Handler
3
+ *
4
+ * Validates GitHub webhook signatures (HMAC-SHA256) and parses payloads
5
+ * for issues, issue comments, discussions, and discussion comments.
6
+ */
7
+ import type { WebhookResult } from './types.ts';
8
+ /**
9
+ * Validate a GitHub webhook signature using HMAC-SHA256.
10
+ *
11
+ * @param rawBody - The raw request body string
12
+ * @param signature - The X-Hub-Signature-256 header value
13
+ * @param secret - The configured webhook secret
14
+ * @returns true if the signature is valid
15
+ */
16
+ export declare function validateSignature(rawBody: string, signature: string, secret: string): boolean;
17
+ /**
18
+ * Parse a GitHub webhook payload and extract a triage-ready result.
19
+ *
20
+ * @param event - The X-GitHub-Event header value
21
+ * @param payload - The parsed JSON payload
22
+ * @returns A WebhookResult for triage, or null if the event should be ignored
23
+ */
24
+ export declare function parsePayload(event: string, payload: Record<string, any>): WebhookResult | null;
25
+ //# sourceMappingURL=github.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/webhooks/github.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAKhD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAQ7F;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,aAAa,GAAG,IAAI,CAa9F"}
@@ -0,0 +1,165 @@
1
+ /**
2
+ * GitHub Webhook Handler
3
+ *
4
+ * Validates GitHub webhook signatures (HMAC-SHA256) and parses payloads
5
+ * for issues, issue comments, discussions, and discussion comments.
6
+ */
7
+ import crypto from 'node:crypto';
8
+ /** Maximum body length included in the summary */
9
+ const MAX_BODY_LENGTH = 500;
10
+ /**
11
+ * Validate a GitHub webhook signature using HMAC-SHA256.
12
+ *
13
+ * @param rawBody - The raw request body string
14
+ * @param signature - The X-Hub-Signature-256 header value
15
+ * @param secret - The configured webhook secret
16
+ * @returns true if the signature is valid
17
+ */
18
+ export function validateSignature(rawBody, signature, secret) {
19
+ if (!signature || !secret)
20
+ return false;
21
+ const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
22
+ // Constant-time comparison to prevent timing attacks
23
+ if (expected.length !== signature.length)
24
+ return false;
25
+ return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
26
+ }
27
+ /**
28
+ * Parse a GitHub webhook payload and extract a triage-ready result.
29
+ *
30
+ * @param event - The X-GitHub-Event header value
31
+ * @param payload - The parsed JSON payload
32
+ * @returns A WebhookResult for triage, or null if the event should be ignored
33
+ */
34
+ export function parsePayload(event, payload) {
35
+ switch (event) {
36
+ case 'issues':
37
+ return parseIssueEvent(payload);
38
+ case 'issue_comment':
39
+ return parseIssueCommentEvent(payload);
40
+ case 'discussion':
41
+ return parseDiscussionEvent(payload);
42
+ case 'discussion_comment':
43
+ return parseDiscussionCommentEvent(payload);
44
+ default:
45
+ return null;
46
+ }
47
+ }
48
+ function parseIssueEvent(payload) {
49
+ const action = payload.action;
50
+ const issue = payload.issue;
51
+ const repo = payload.repository?.full_name;
52
+ if (!issue || !repo)
53
+ return null;
54
+ // Only handle opened, closed, reopened
55
+ const directActions = ['opened', 'closed', 'reopened'];
56
+ if (directActions.includes(action)) {
57
+ return {
58
+ source: 'github-webhook',
59
+ sourceId: `github:issues:${action}:${repo}#${issue.number}`,
60
+ summary: formatIssueSummary(repo, issue, action),
61
+ rawPayload: payload,
62
+ };
63
+ }
64
+ // Handle labeled — only if the label is "kb-candidate"
65
+ if (action === 'labeled') {
66
+ const label = payload.label;
67
+ if (label?.name === 'kb-candidate') {
68
+ return {
69
+ source: 'github-webhook',
70
+ sourceId: `github:issues:labeled:${repo}#${issue.number}`,
71
+ summary: formatIssueSummary(repo, issue, 'labeled'),
72
+ rawPayload: payload,
73
+ };
74
+ }
75
+ return null;
76
+ }
77
+ return null;
78
+ }
79
+ function parseIssueCommentEvent(payload) {
80
+ const action = payload.action;
81
+ if (action !== 'created')
82
+ return null;
83
+ const comment = payload.comment;
84
+ const issue = payload.issue;
85
+ const repo = payload.repository?.full_name;
86
+ if (!comment || !issue || !repo)
87
+ return null;
88
+ const body = truncate(comment.body || '');
89
+ const summary = [
90
+ `[GitHub Comment] ${repo}#${issue.number}: "${issue.title}" (comment by ${comment.user?.login || 'unknown'})`,
91
+ '---',
92
+ body,
93
+ ].join('\n');
94
+ return {
95
+ source: 'github-webhook',
96
+ sourceId: `github:issue_comment:${comment.id}`,
97
+ summary,
98
+ rawPayload: payload,
99
+ };
100
+ }
101
+ function parseDiscussionEvent(payload) {
102
+ const action = payload.action;
103
+ if (action !== 'created' && action !== 'answered')
104
+ return null;
105
+ const discussion = payload.discussion;
106
+ const repo = payload.repository?.full_name;
107
+ if (!discussion || !repo)
108
+ return null;
109
+ const body = truncate(discussion.body || '');
110
+ const category = discussion.category?.name;
111
+ const summary = [
112
+ `[GitHub Discussion] ${repo}#${discussion.number}: "${discussion.title}" (${action} by ${discussion.user?.login || 'unknown'})`,
113
+ category ? `Category: ${category}` : '',
114
+ '---',
115
+ body,
116
+ ]
117
+ .filter(Boolean)
118
+ .join('\n');
119
+ return {
120
+ source: 'github-webhook',
121
+ sourceId: `github:discussion:${action}:${repo}#${discussion.number}`,
122
+ summary,
123
+ rawPayload: payload,
124
+ };
125
+ }
126
+ function parseDiscussionCommentEvent(payload) {
127
+ const action = payload.action;
128
+ if (action !== 'created')
129
+ return null;
130
+ const comment = payload.comment;
131
+ const discussion = payload.discussion;
132
+ const repo = payload.repository?.full_name;
133
+ if (!comment || !discussion || !repo)
134
+ return null;
135
+ const body = truncate(comment.body || '');
136
+ const summary = [
137
+ `[GitHub Discussion Comment] ${repo}#${discussion.number}: "${discussion.title}" (comment by ${comment.user?.login || 'unknown'})`,
138
+ '---',
139
+ body,
140
+ ].join('\n');
141
+ return {
142
+ source: 'github-webhook',
143
+ sourceId: `github:discussion_comment:${comment.id}`,
144
+ summary,
145
+ rawPayload: payload,
146
+ };
147
+ }
148
+ function formatIssueSummary(repo, issue, action) {
149
+ const labels = (issue.labels || []).map((l) => l.name).join(', ');
150
+ const body = truncate(issue.body || '');
151
+ const parts = [
152
+ `[GitHub Issue] ${repo}#${issue.number}: "${issue.title}" (${action} by ${issue.user?.login || 'unknown'})`,
153
+ ];
154
+ if (labels)
155
+ parts.push(`Labels: ${labels}`);
156
+ parts.push('---');
157
+ parts.push(body);
158
+ return parts.join('\n');
159
+ }
160
+ function truncate(text) {
161
+ if (text.length <= MAX_BODY_LENGTH)
162
+ return text;
163
+ return text.slice(0, MAX_BODY_LENGTH) + '...';
164
+ }
165
+ //# sourceMappingURL=github.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/webhooks/github.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Webhook Middleware
3
+ *
4
+ * HTTP middleware for Harper's scope.server.http() that routes
5
+ * /webhooks/<kbId>/<provider>/<secret> requests to the appropriate
6
+ * webhook handler after validating the per-KB secret.
7
+ */
8
+ import type { Scope, HarperRequest } from '../types.ts';
9
+ /**
10
+ * Create a webhook middleware function for Harper's scope.server.http().
11
+ *
12
+ * URL format: /webhooks/<kbId>/<provider>/<secret>
13
+ *
14
+ * The secret is validated against the WebhookEndpoint table for the
15
+ * given KB and provider. The same secret is used to verify the GitHub
16
+ * HMAC payload signature.
17
+ */
18
+ export declare function createWebhookMiddleware(scope: Scope): (request: HarperRequest, next: (req: HarperRequest) => Promise<unknown>) => Promise<unknown>;
19
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/webhooks/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAcxD;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACtC,KAAK,EAAE,KAAK,GACV,CAAC,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAyC9F"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Webhook Middleware
3
+ *
4
+ * HTTP middleware for Harper's scope.server.http() that routes
5
+ * /webhooks/<kbId>/<provider>/<secret> requests to the appropriate
6
+ * webhook handler after validating the per-KB secret.
7
+ */
8
+ import { readBody } from "../http-utils.js";
9
+ import { submitTriage, findBySourceId } from "../core/triage.js";
10
+ import { validateWebhookSecret } from "../core/webhook-endpoints.js";
11
+ import { validateSignature as validateGitHubSignature, parsePayload as parseGitHubPayload } from "./github.js";
12
+ /**
13
+ * Check if a delivery ID has already been processed, using a TTL table
14
+ * so dedup is consistent across all workers.
15
+ */
16
+ async function isDuplicateDelivery(deliveryId, kbId, provider) {
17
+ const existing = await databases.kb.WebhookDelivery.get(deliveryId);
18
+ if (existing)
19
+ return true;
20
+ await databases.kb.WebhookDelivery.put({ id: deliveryId, kbId, provider });
21
+ return false;
22
+ }
23
+ /**
24
+ * Create a webhook middleware function for Harper's scope.server.http().
25
+ *
26
+ * URL format: /webhooks/<kbId>/<provider>/<secret>
27
+ *
28
+ * The secret is validated against the WebhookEndpoint table for the
29
+ * given KB and provider. The same secret is used to verify the GitHub
30
+ * HMAC payload signature.
31
+ */
32
+ export function createWebhookMiddleware(scope) {
33
+ const scopeLogger = scope.logger;
34
+ return async (request, next) => {
35
+ const pathname = request.pathname || '';
36
+ // Only handle /webhooks/* routes
37
+ if (!pathname.startsWith('/webhooks/')) {
38
+ return next(request);
39
+ }
40
+ // Only accept POST
41
+ if (request.method !== 'POST') {
42
+ return jsonResponse(405, { error: 'Method not allowed' });
43
+ }
44
+ // Extract kbId, provider, and secret from path:
45
+ // /webhooks/<kbId>/<provider>/<secret>
46
+ const parts = pathname.replace(/^\/webhooks\//, '').split('/');
47
+ if (parts.length < 3 || !parts[0] || !parts[1] || !parts[2]) {
48
+ return jsonResponse(400, {
49
+ error: 'Invalid webhook path. Use /webhooks/<kbId>/<provider>/<secret>',
50
+ });
51
+ }
52
+ const kbId = parts[0];
53
+ const provider = parts[1];
54
+ const secret = parts[2];
55
+ // Validate the secret against the WebhookEndpoint table
56
+ const endpoint = await validateWebhookSecret(secret, kbId, provider);
57
+ if (!endpoint) {
58
+ return jsonResponse(404, { error: 'Unknown webhook endpoint' });
59
+ }
60
+ // Route to the appropriate handler
61
+ if (provider === 'github') {
62
+ return handleGitHub(request, secret, kbId, scopeLogger);
63
+ }
64
+ return jsonResponse(404, { error: 'Unknown webhook provider' });
65
+ };
66
+ }
67
+ async function handleGitHub(request, secret, kbId, scopeLogger) {
68
+ // Read raw body
69
+ const rawBody = await readBody(request);
70
+ // Validate HMAC signature using the secret from the URL
71
+ const signature = getHeader(request, 'x-hub-signature-256');
72
+ if (!validateGitHubSignature(rawBody, signature, secret)) {
73
+ return jsonResponse(401, { error: 'Invalid signature' });
74
+ }
75
+ // Replay protection — reject duplicate delivery IDs
76
+ const deliveryId = getHeader(request, 'x-github-delivery');
77
+ if (deliveryId && (await isDuplicateDelivery(deliveryId, kbId, 'github'))) {
78
+ return jsonResponse(200, { status: 'duplicate', deliveryId });
79
+ }
80
+ // Parse payload
81
+ let payload;
82
+ try {
83
+ payload = JSON.parse(rawBody);
84
+ }
85
+ catch {
86
+ return jsonResponse(400, { error: 'Invalid JSON' });
87
+ }
88
+ const event = getHeader(request, 'x-github-event');
89
+ const result = parseGitHubPayload(event, payload);
90
+ if (!result) {
91
+ // Event type we don't handle — acknowledge without creating triage item
92
+ return jsonResponse(200, { status: 'ignored' });
93
+ }
94
+ return submitResult(kbId, result, scopeLogger);
95
+ }
96
+ /**
97
+ * Submit a webhook result to the triage queue, checking for duplicates first.
98
+ */
99
+ async function submitResult(kbId, result, scopeLogger) {
100
+ // Idempotency check
101
+ const existing = await findBySourceId(kbId, result.sourceId);
102
+ if (existing) {
103
+ return jsonResponse(200, { status: 'duplicate', triageId: existing.id });
104
+ }
105
+ const item = await submitTriage(kbId, result.source, result.summary, result.rawPayload, result.sourceId);
106
+ scopeLogger?.info?.(`Webhook triage item created: ${item.id} (${result.source})`);
107
+ return jsonResponse(200, { status: 'accepted', triageId: item.id });
108
+ }
109
+ /**
110
+ * Get a header value from Harper's request, case-insensitive.
111
+ */
112
+ function getHeader(request, name) {
113
+ const headers = request.headers;
114
+ if (!headers)
115
+ return '';
116
+ // Try direct access (case-sensitive)
117
+ const direct = headers[name] ?? headers[name.toLowerCase()];
118
+ if (direct !== undefined) {
119
+ return Array.isArray(direct) ? direct[0] : String(direct);
120
+ }
121
+ // Try .get() method (Harper's Headers class)
122
+ if (typeof headers.get === 'function') {
123
+ const val = headers.get(name);
124
+ if (val !== undefined && val !== null)
125
+ return String(val);
126
+ }
127
+ // Fallback: iterate to find case-insensitive match
128
+ const lowerName = name.toLowerCase();
129
+ if (typeof headers === 'object') {
130
+ for (const [key, value] of Object.entries(headers)) {
131
+ if (key.toLowerCase() === lowerName && value !== undefined) {
132
+ return Array.isArray(value) ? value[0] : String(value);
133
+ }
134
+ }
135
+ }
136
+ return '';
137
+ }
138
+ function jsonResponse(status, body) {
139
+ return new Response(JSON.stringify(body), {
140
+ status,
141
+ headers: { 'Content-Type': 'application/json' },
142
+ });
143
+ }
144
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/webhooks/middleware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Shared types for webhook handlers.
3
+ */
4
+ /**
5
+ * Result from parsing a webhook payload.
6
+ * Returned by webhook handlers for the middleware to submit to triage.
7
+ */
8
+ export interface WebhookResult {
9
+ /** Source identifier (e.g., "github-webhook") */
10
+ source: string;
11
+ /** Deduplication key for idempotency */
12
+ sourceId: string;
13
+ /** Human-readable summary for triage review */
14
+ summary: string;
15
+ /** Original raw payload */
16
+ rawPayload: unknown;
17
+ }
18
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/webhooks/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC7B,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,UAAU,EAAE,OAAO,CAAC;CACpB"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Shared types for webhook handlers.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/webhooks/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "harper-kb",
3
+ "version": "0.2.0",
4
+ "description": "Knowledge base plugin for Harper with MCP server integration",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ },
13
+ "./config": "./config.yaml"
14
+ },
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "dev": "tsc --watch",
18
+ "test": "npm run build && node --test \"test/**/*.test.js\"",
19
+ "test:watch": "npm run build && node --test --watch \"test/**/*.test.js\"",
20
+ "test:coverage": "npm run build && node --enable-source-maps --test --experimental-test-coverage --test-coverage-exclude='test/**' --test-coverage-exclude='**/harperdb/**' \"test/**/*.test.js\"",
21
+ "lint": "oxlint --deny-warnings .",
22
+ "lint:fix": "oxlint --deny-warnings --fix .",
23
+ "format": "prettier --write .",
24
+ "format:check": "prettier --check .",
25
+ "prepublishOnly": "npm run build"
26
+ },
27
+ "keywords": [
28
+ "harper",
29
+ "harperdb",
30
+ "plugin",
31
+ "knowledge-base",
32
+ "mcp",
33
+ "ai",
34
+ "embeddings",
35
+ "vector-search"
36
+ ],
37
+ "author": "Nathan Heskew <nathan@heskew.dev> (https://heskew.dev)",
38
+ "license": "MIT",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/heskew/harper-kb"
42
+ },
43
+ "dependencies": {
44
+ "jose": "^6.1.3"
45
+ },
46
+ "devDependencies": {
47
+ "@harperdb/code-guidelines": "^0.0.6",
48
+ "@types/node": "^22.0.0",
49
+ "oxlint": "^1.31.0",
50
+ "prettier": "^3.7.0",
51
+ "typescript": "^5.7.0"
52
+ },
53
+ "optionalDependencies": {
54
+ "harper-fabric-embeddings": "^0.1.0"
55
+ },
56
+ "peerDependencies": {
57
+ "harperdb": ">=4.7.0"
58
+ },
59
+ "engines": {
60
+ "node": ">=22"
61
+ },
62
+ "files": [
63
+ "dist",
64
+ "schema",
65
+ "config.yaml",
66
+ "README.md",
67
+ "LICENSE"
68
+ ]
69
+ }
@@ -0,0 +1,136 @@
1
+ ## Knowledge Base Plugin Schema
2
+ ## Defines all tables for the knowledge base in the "kb" database
3
+
4
+ ## Knowledge base registry — one record per tenant
5
+ type KnowledgeBase @table(database: "kb") @export {
6
+ id: ID @primaryKey
7
+ name: String
8
+ description: String
9
+ settings: Any
10
+ createdBy: String
11
+ createdAt: Date @createdTime
12
+ updatedAt: Date @updatedTime
13
+ }
14
+
15
+ ## Core knowledge entries with vector embeddings for semantic search
16
+ type KnowledgeEntry @table(database: "kb") @export {
17
+ id: ID @primaryKey
18
+ kbId: ID @indexed
19
+ kb: KnowledgeBase @relationship(from: "kbId")
20
+ title: String @indexed
21
+ content: String
22
+ tags: [String]
23
+ appliesTo: Any
24
+ source: String
25
+ sourceUrl: String
26
+ references: Any
27
+ confidence: String @indexed
28
+ addedBy: String
29
+ reviewedBy: String
30
+ embedding: [Float] @indexed(type: "HNSW", distance: "cosine")
31
+ supersedesId: ID
32
+ supersedes: KnowledgeEntry @relationship(from: "supersedesId")
33
+ supersededById: ID
34
+ supersededBy: KnowledgeEntry @relationship(from: "supersededById")
35
+ siblingIds: [ID]
36
+ siblings: [KnowledgeEntry] @relationship(from: "siblingIds")
37
+ relatedIds: [ID]
38
+ relatedEntries: [KnowledgeEntry] @relationship(from: "relatedIds")
39
+ metadata: Any
40
+ deprecated: Boolean @indexed
41
+ createdAt: Date @createdTime
42
+ updatedAt: Date @updatedTime
43
+ }
44
+
45
+ ## Webhook intake queue for new knowledge submissions
46
+ ## 7-day TTL (604800 seconds)
47
+ type TriageItem @table(database: "kb", expiration: 604800) {
48
+ id: ID @primaryKey
49
+ kbId: ID @indexed
50
+ kb: KnowledgeBase @relationship(from: "kbId")
51
+ source: String @indexed
52
+ sourceId: String @indexed
53
+ rawPayload: Any
54
+ summary: String
55
+ status: String @indexed
56
+ matchedEntryId: ID
57
+ matchedEntry: KnowledgeEntry @relationship(from: "matchedEntryId")
58
+ draftEntryId: ID
59
+ draftEntry: KnowledgeEntry @relationship(from: "draftEntryId")
60
+ action: String
61
+ processedBy: String
62
+ createdAt: Date @createdTime
63
+ processedAt: Date
64
+ }
65
+
66
+ ## Tag registry with descriptions and usage counts
67
+ type KnowledgeTag @table(database: "kb") {
68
+ id: ID @primaryKey
69
+ kbId: ID @indexed
70
+ kb: KnowledgeBase @relationship(from: "kbId")
71
+ description: String
72
+ entryCount: Int
73
+ }
74
+
75
+ ## Search query analytics log
76
+ ## 30-day TTL (2592000 seconds)
77
+ type QueryLog @table(database: "kb", expiration: 2592000) {
78
+ id: ID @primaryKey
79
+ kbId: ID @indexed
80
+ kb: KnowledgeBase @relationship(from: "kbId")
81
+ query: String
82
+ context: Any
83
+ source: String
84
+ resultCount: Int
85
+ topResultId: ID
86
+ topResult: KnowledgeEntry @relationship(from: "topResultId")
87
+ createdAt: Date @createdTime
88
+ }
89
+
90
+ ## API keys for webhooks and service accounts
91
+ type ServiceKey @table(database: "kb") {
92
+ id: ID @primaryKey
93
+ kbId: ID @indexed
94
+ kb: KnowledgeBase @relationship(from: "kbId")
95
+ name: String
96
+ keyHash: String
97
+ role: String
98
+ permissions: Any
99
+ createdBy: String
100
+ createdAt: Date @createdTime
101
+ lastUsedAt: Date
102
+ }
103
+
104
+ ## Webhook delivery dedup — id is the delivery ID from the provider
105
+ ## 1-hour TTL (3600 seconds) — enough to catch replays, auto-cleans
106
+ type WebhookDelivery @table(database: "kb", expiration: 3600) {
107
+ id: ID @primaryKey
108
+ kbId: String
109
+ provider: String
110
+ createdAt: Date @createdTime
111
+ }
112
+
113
+ ## Webhook endpoint secrets — one per KB+provider, id = SHA-256(secret)
114
+ type WebhookEndpoint @table(database: "kb") @export {
115
+ id: ID @primaryKey
116
+ kbId: ID @indexed
117
+ kb: KnowledgeBase @relationship(from: "kbId")
118
+ provider: String
119
+ label: String
120
+ createdBy: String
121
+ createdAt: Date @createdTime
122
+ }
123
+
124
+ ## Edit history for knowledge entries — append-only audit log
125
+ type KnowledgeEntryEdit @table(database: "kb") {
126
+ id: ID @primaryKey
127
+ kbId: ID @indexed
128
+ kb: KnowledgeBase @relationship(from: "kbId")
129
+ entryId: ID @indexed
130
+ entry: KnowledgeEntry @relationship(from: "entryId")
131
+ editedBy: String @indexed
132
+ editSummary: String
133
+ previousSnapshot: Any
134
+ changedFields: [String]
135
+ createdAt: Date @createdTime
136
+ }