@pithy-sh/support 0.5.1 → 0.6.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 +8 -0
- package/dist/audit/actions.d.ts +9 -0
- package/dist/audit/actions.d.ts.map +1 -1
- package/dist/audit/actions.js +9 -0
- package/dist/capability.d.ts +2 -1
- package/dist/capability.d.ts.map +1 -1
- package/dist/capability.js +30 -6
- package/dist/config/config.d.ts +63 -2
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +63 -5
- package/dist/data/assignment.d.ts +43 -0
- package/dist/data/assignment.d.ts.map +1 -0
- package/dist/data/assignment.js +38 -0
- package/dist/data/embedding.d.ts +21 -0
- package/dist/data/embedding.d.ts.map +1 -0
- package/dist/data/embedding.js +23 -0
- package/dist/data/tables.d.ts +28 -0
- package/dist/data/tables.d.ts.map +1 -1
- package/dist/data/tables.js +10 -2
- package/dist/data/thread.d.ts +9 -4
- package/dist/data/thread.d.ts.map +1 -1
- package/dist/data/thread.js +9 -4
- package/dist/http/guards.d.ts +32 -14
- package/dist/http/guards.d.ts.map +1 -1
- package/dist/http/guards.js +44 -16
- package/dist/http/handlers.d.ts +35 -2
- package/dist/http/handlers.d.ts.map +1 -1
- package/dist/http/handlers.js +81 -8
- package/dist/http/resolve.d.ts +8 -0
- package/dist/http/resolve.d.ts.map +1 -1
- package/dist/http/resolve.js +20 -1
- package/dist/http/responses.d.ts +355 -0
- package/dist/http/responses.d.ts.map +1 -1
- package/dist/http/responses.js +64 -2
- package/dist/http/routes.d.ts +25 -11
- package/dist/http/routes.d.ts.map +1 -1
- package/dist/http/routes.js +34 -5
- package/dist/http/schemas.d.ts +67 -3
- package/dist/http/schemas.d.ts.map +1 -1
- package/dist/http/schemas.js +44 -5
- package/dist/http/scopes.d.ts +10 -5
- package/dist/http/scopes.d.ts.map +1 -1
- package/dist/http/scopes.js +42 -6
- package/dist/http/views.d.ts +9 -1
- package/dist/http/views.d.ts.map +1 -1
- package/dist/http/views.js +40 -1
- package/dist/inbound/ingest.d.ts +1 -1
- package/dist/inbound/ingest.d.ts.map +1 -1
- package/dist/inbound/ingest.js +3 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -4
- package/dist/migrations/0002_assignment.d.ts +20 -0
- package/dist/migrations/0002_assignment.d.ts.map +1 -0
- package/dist/migrations/0002_assignment.js +45 -0
- package/dist/migrations/0003_embeddings.d.ts +15 -0
- package/dist/migrations/0003_embeddings.d.ts.map +1 -0
- package/dist/migrations/0003_embeddings.js +23 -0
- package/dist/migrations/set.d.ts +13 -0
- package/dist/migrations/set.d.ts.map +1 -0
- package/dist/migrations/set.js +21 -0
- package/dist/presence/room.d.ts +35 -0
- package/dist/presence/room.d.ts.map +1 -0
- package/dist/presence/room.js +66 -0
- package/dist/provision/provisionSupport.d.ts +32 -0
- package/dist/provision/provisionSupport.d.ts.map +1 -1
- package/dist/provision/provisionSupport.js +10 -2
- package/dist/provision/resolveSupportConfig.d.ts.map +1 -1
- package/dist/provision/resolveSupportConfig.js +13 -2
- package/dist/purge/contribution.d.ts +49 -0
- package/dist/purge/contribution.d.ts.map +1 -0
- package/dist/purge/contribution.js +164 -0
- package/dist/secret/registry.d.ts +26 -2
- package/dist/secret/registry.d.ts.map +1 -1
- package/dist/secret/registry.js +15 -3
- package/dist/semantic/documents.d.ts +21 -0
- package/dist/semantic/documents.d.ts.map +1 -0
- package/dist/semantic/documents.js +128 -0
- package/dist/semantic/embed.d.ts +59 -0
- package/dist/semantic/embed.d.ts.map +1 -0
- package/dist/semantic/embed.js +59 -0
- package/dist/semantic/messageIndex.d.ts +46 -0
- package/dist/semantic/messageIndex.d.ts.map +1 -0
- package/dist/semantic/messageIndex.js +67 -0
- package/dist/semantic/query.d.ts +37 -0
- package/dist/semantic/query.d.ts.map +1 -0
- package/dist/semantic/query.js +46 -0
- package/dist/staff/staff.d.ts +22 -0
- package/dist/staff/staff.d.ts.map +1 -0
- package/dist/staff/staff.js +64 -0
- package/dist/store/assignment.d.ts +63 -0
- package/dist/store/assignment.d.ts.map +1 -0
- package/dist/store/assignment.js +86 -0
- package/dist/store/hybrid.d.ts +134 -0
- package/dist/store/hybrid.d.ts.map +1 -0
- package/dist/store/hybrid.js +185 -0
- package/dist/store/paging.d.ts +10 -0
- package/dist/store/paging.d.ts.map +1 -1
- package/dist/store/paging.js +11 -1
- package/dist/store/provisionIndex.d.ts +21 -0
- package/dist/store/provisionIndex.d.ts.map +1 -0
- package/dist/store/provisionIndex.js +36 -0
- package/dist/store/search.d.ts +18 -9
- package/dist/store/search.d.ts.map +1 -1
- package/dist/store/search.js +36 -34
- package/dist/store/searchIndex.d.ts +4 -4
- package/dist/store/searchIndex.js +4 -4
- package/dist/store/threads.d.ts +174 -8
- package/dist/store/threads.d.ts.map +1 -1
- package/dist/store/threads.js +33 -40
- package/dist/submission/submit.d.ts +1 -1
- package/dist/submission/submit.d.ts.map +1 -1
- package/dist/submission/submit.js +2 -1
- package/dist/test-utils/seed.d.ts +33 -0
- package/dist/test-utils/seed.d.ts.map +1 -0
- package/dist/test-utils/seed.js +102 -0
- package/dist/test-utils/semantic.d.ts +21 -0
- package/dist/test-utils/semantic.d.ts.map +1 -0
- package/dist/test-utils/semantic.js +107 -0
- package/dist/version.generated.d.ts +1 -1
- package/dist/version.generated.js +1 -1
- package/dist/workflows/specs.d.ts +23 -0
- package/dist/workflows/specs.d.ts.map +1 -1
- package/dist/workflows/specs.js +27 -7
- package/dist/workflows/worker.d.ts +15 -2
- package/dist/workflows/worker.d.ts.map +1 -1
- package/dist/workflows/worker.js +48 -4
- package/package.json +9 -7
- package/pithy.manifest.json +21 -3
- package/src/audit/actions.ts +9 -0
- package/src/capability.ts +43 -4
- package/src/config/config.ts +104 -5
- package/src/data/assignment.ts +55 -0
- package/src/data/embedding.ts +27 -0
- package/src/data/tables.ts +8 -0
- package/src/data/thread.ts +26 -4
- package/src/http/guards.ts +52 -15
- package/src/http/handlers.ts +125 -4
- package/src/http/resolve.ts +19 -0
- package/src/http/responses.ts +154 -0
- package/src/http/routes.ts +98 -12
- package/src/http/schemas.ts +117 -28
- package/src/http/scopes.ts +43 -6
- package/src/http/views.ts +44 -0
- package/src/inbound/ingest.ts +5 -2
- package/src/index.ts +5 -0
- package/src/migrations/0002_assignment.ts +65 -0
- package/src/migrations/0003_embeddings.ts +29 -0
- package/src/migrations/set.ts +21 -0
- package/src/presence/room.ts +94 -0
- package/src/provision/provisionSupport.ts +33 -1
- package/src/provision/resolveSupportConfig.ts +24 -13
- package/src/purge/contribution.ts +294 -0
- package/src/secret/registry.ts +17 -2
- package/src/semantic/documents.ts +178 -0
- package/src/semantic/embed.ts +99 -0
- package/src/semantic/messageIndex.ts +74 -0
- package/src/semantic/query.ts +66 -0
- package/src/staff/staff.ts +128 -0
- package/src/store/assignment.ts +179 -0
- package/src/store/hybrid.ts +314 -0
- package/src/store/paging.ts +14 -0
- package/src/store/provisionIndex.ts +46 -0
- package/src/store/search.ts +58 -37
- package/src/store/searchIndex.ts +4 -4
- package/src/store/threads.ts +91 -91
- package/src/submission/submit.ts +3 -2
- package/src/test-utils/seed.ts +141 -0
- package/src/test-utils/semantic.ts +110 -0
- package/src/version.generated.ts +1 -1
- package/src/workflows/specs.ts +34 -0
- package/src/workflows/worker.ts +84 -8
- package/src/workflows/wrangler.jsonc +8 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../../src/inbound/ingest.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAEnE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kCAAkC,CAAC;AAG/D,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../../src/inbound/ingest.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAEnE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kCAAkC,CAAC;AAG/D,OAAO,EAAE,KAAK,aAAa,EAAmB,MAAM,kBAAkB,CAAC;AAGvE,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAUxB;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,uBAAuB;AACvB,MAAM,MAAM,aAAa;AACvB,oFAAoF;AAClF;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE;AAC7C,wDAAwD;GACtD;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AAC3D,yEAAyE;GACvE;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AACzE,cAAc;GACZ;IACE,OAAO,EAAE,IAAI,CAAC;IACd,SAAS,EAAE,KAAK,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,SAAS,EAAE,OAAO,CAAC;IACnB,8EAA8E;IAC9E,WAAW,EAAE,MAAM,CAAC;IACpB,iGAAiG;IACjG,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAEN,+CAA+C;AAC/C,MAAM,WAAW,UAAU;IACzB,0BAA0B;IAC1B,EAAE,EAAE,eAAe,CAAC;IACpB,2BAA2B;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,+FAA+F;IAC/F,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB;;;;;OAKG;IACH,gBAAgB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1D,oFAAoF;IACpF,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACxD,sBAAsB;IACtB,IAAI,EAAE,SAAS,CAAC;IAChB,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,yBAAyB;IACzB,KAAK,EAAE,MAAM,MAAM,CAAC;IACpB,WAAW;IACX,GAAG,EAAE,MAAM,IAAI,CAAC;CACjB;AAED,iFAAiF;AACjF,MAAM,WAAW,WAAW;IAC1B,0BAA0B;IAC1B,GAAG,EAAE,WAAW,CAAC;IACjB,wGAAwG;IACxG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8FAA8F;IAC9F,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA0ID,kCAAkC;AAClC,wBAAsB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CA8RhG"}
|
package/dist/inbound/ingest.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
|
+
import { supportSemantic } from "../config/config.js";
|
|
3
4
|
import { SupportAttachment } from "../data/attachment.js";
|
|
4
5
|
import { SupportMessage } from "../data/message.js";
|
|
5
6
|
import { SupportThread, UNCLASSIFIED } from "../data/thread.js";
|
|
@@ -292,7 +293,8 @@ async function ingestInbound(deps, input) {
|
|
|
292
293
|
});
|
|
293
294
|
}
|
|
294
295
|
const classifying = deps.config.ai.enabled && !parsed.autoSubmitted;
|
|
295
|
-
|
|
296
|
+
const embedding = supportSemantic(deps.config.search) !== void 0 && !parsed.autoSubmitted;
|
|
297
|
+
if (classifying || embedding) try {
|
|
296
298
|
await deps.dispatchClassify(messageId);
|
|
297
299
|
} catch (error) {
|
|
298
300
|
deps.log.warn("support classification dispatch failed", {
|
package/dist/index.d.ts
CHANGED
|
@@ -8,15 +8,17 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export { type SupportAuditAction, SupportAuditActions } from "./audit/actions";
|
|
10
10
|
export { isSupportCapability, SUPPORT_MIGRATION_ORDER, type SupportCapability, type SupportOptions, support, } from "./capability";
|
|
11
|
-
export { DEFAULT_CLASSIFY_MODEL, SupportAiConfig, SupportAttachmentsConfig, SupportConfig, type SupportConfigInput, SupportGuardConfig, SupportReplyConfig, SupportSearchConfig, } from "./config/config";
|
|
11
|
+
export { DEFAULT_CLASSIFY_MODEL, SupportAiConfig, SupportAttachmentsConfig, SupportConfig, type SupportConfigInput, SupportGuardConfig, SupportReplyConfig, SupportSearchConfig, SupportStaffConfig, } from "./config/config";
|
|
12
|
+
export { SupportAssignment, SupportAssignmentActorType, UNASSIGNED } from "./data/assignment";
|
|
12
13
|
export { SupportAttachment } from "./data/attachment";
|
|
13
14
|
export { DEFAULT_SUPPORT_CATEGORIES, defineSupportCategories, type SupportCategories, } from "./data/categories";
|
|
14
15
|
export { SupportClassification } from "./data/classification";
|
|
15
16
|
export { SupportMessageDirection, SupportPriority, SupportSentiment, UNCATEGORIZED } from "./data/enums";
|
|
16
17
|
export { SupportThreadFlag } from "./data/flag";
|
|
17
18
|
export { SupportMessage } from "./data/message";
|
|
18
|
-
export { SUPPORT_ATTACHMENTS_TABLE, SUPPORT_CLASSIFICATIONS_TABLE, SUPPORT_FLAGS_TABLE, SUPPORT_MESSAGES_TABLE, SUPPORT_SEARCH_TABLE, SUPPORT_THREADS_TABLE, type SupportDatabase, supportDatabase, } from "./data/tables";
|
|
19
|
+
export { SUPPORT_ASSIGNMENTS_TABLE, SUPPORT_ATTACHMENTS_TABLE, SUPPORT_CLASSIFICATIONS_TABLE, SUPPORT_FLAGS_TABLE, SUPPORT_MESSAGES_TABLE, SUPPORT_SEARCH_TABLE, SUPPORT_THREADS_TABLE, type SupportDatabase, supportDatabase, } from "./data/tables";
|
|
19
20
|
export { SupportThread } from "./data/thread";
|
|
20
|
-
export { SUPPORT_CONTROL_PLANE_SCOPES, SUPPORT_THREADS_ARCHIVE_SCOPE, SUPPORT_THREADS_FLAG_SCOPE, SUPPORT_THREADS_READ_SCOPE, SUPPORT_THREADS_RECLASSIFY_SCOPE, SUPPORT_THREADS_REPLY_SCOPE, } from "./http/scopes";
|
|
21
|
+
export { SUPPORT_CONTROL_PLANE_SCOPES, SUPPORT_THREADS_ARCHIVE_SCOPE, SUPPORT_THREADS_ASSIGN_SCOPE, SUPPORT_THREADS_FLAG_SCOPE, SUPPORT_THREADS_READ_SCOPE, SUPPORT_THREADS_RECLASSIFY_SCOPE, SUPPORT_THREADS_REPLY_SCOPE, } from "./http/scopes";
|
|
22
|
+
export { SUPPORT_THREAD_ACTIVITIES, SUPPORT_THREAD_ROOM } from "./presence/room";
|
|
21
23
|
export { DEFAULT_SUPPORT_REPLIES, defineSupportReplies, SupportReplySnippet, type SupportReplySnippets, } from "./reply/snippets";
|
|
22
24
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,OAAO,GACR,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,wBAAwB,EACxB,aAAa,EACb,KAAK,kBAAkB,EACvB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,OAAO,GACR,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,wBAAwB,EACxB,aAAa,EACb,KAAK,kBAAkB,EACvB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC9F,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EACL,0BAA0B,EAC1B,uBAAuB,EACvB,KAAK,iBAAiB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACzG,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EACL,yBAAyB,EACzB,yBAAyB,EACzB,6BAA6B,EAC7B,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EACrB,KAAK,eAAe,EACpB,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EACL,4BAA4B,EAC5B,6BAA6B,EAC7B,4BAA4B,EAC5B,0BAA0B,EAC1B,0BAA0B,EAC1B,gCAAgC,EAChC,2BAA2B,GAC5B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACjF,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,KAAK,oBAAoB,GAC1B,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
import { DEFAULT_SUPPORT_REPLIES, SupportReplySnippet, defineSupportReplies } from "./reply/snippets.js";
|
|
4
|
-
import { DEFAULT_CLASSIFY_MODEL, SupportAiConfig, SupportAttachmentsConfig, SupportConfig, SupportGuardConfig, SupportReplyConfig, SupportSearchConfig } from "./config/config.js";
|
|
4
|
+
import { DEFAULT_CLASSIFY_MODEL, SupportAiConfig, SupportAttachmentsConfig, SupportConfig, SupportGuardConfig, SupportReplyConfig, SupportSearchConfig, SupportStaffConfig } from "./config/config.js";
|
|
5
5
|
import { SupportMessageDirection, SupportPriority, SupportSentiment, UNCATEGORIZED } from "./data/enums.js";
|
|
6
6
|
import { DEFAULT_SUPPORT_CATEGORIES, defineSupportCategories } from "./data/categories.js";
|
|
7
|
+
import { SupportAssignment, SupportAssignmentActorType, UNASSIGNED } from "./data/assignment.js";
|
|
7
8
|
import { SupportAttachment } from "./data/attachment.js";
|
|
8
9
|
import { SupportClassification } from "./data/classification.js";
|
|
9
10
|
import { SupportThreadFlag } from "./data/flag.js";
|
|
10
11
|
import { SupportMessage } from "./data/message.js";
|
|
11
12
|
import { SupportThread } from "./data/thread.js";
|
|
12
|
-
import { SUPPORT_ATTACHMENTS_TABLE, SUPPORT_CLASSIFICATIONS_TABLE, SUPPORT_FLAGS_TABLE, SUPPORT_MESSAGES_TABLE, SUPPORT_SEARCH_TABLE, SUPPORT_THREADS_TABLE, supportDatabase } from "./data/tables.js";
|
|
13
|
+
import { SUPPORT_ASSIGNMENTS_TABLE, SUPPORT_ATTACHMENTS_TABLE, SUPPORT_CLASSIFICATIONS_TABLE, SUPPORT_FLAGS_TABLE, SUPPORT_MESSAGES_TABLE, SUPPORT_SEARCH_TABLE, SUPPORT_THREADS_TABLE, supportDatabase } from "./data/tables.js";
|
|
13
14
|
import { SupportAuditActions } from "./audit/actions.js";
|
|
14
|
-
import { SUPPORT_CONTROL_PLANE_SCOPES, SUPPORT_THREADS_ARCHIVE_SCOPE, SUPPORT_THREADS_FLAG_SCOPE, SUPPORT_THREADS_READ_SCOPE, SUPPORT_THREADS_RECLASSIFY_SCOPE, SUPPORT_THREADS_REPLY_SCOPE } from "./http/scopes.js";
|
|
15
|
+
import { SUPPORT_CONTROL_PLANE_SCOPES, SUPPORT_THREADS_ARCHIVE_SCOPE, SUPPORT_THREADS_ASSIGN_SCOPE, SUPPORT_THREADS_FLAG_SCOPE, SUPPORT_THREADS_READ_SCOPE, SUPPORT_THREADS_RECLASSIFY_SCOPE, SUPPORT_THREADS_REPLY_SCOPE } from "./http/scopes.js";
|
|
16
|
+
import { SUPPORT_THREAD_ACTIVITIES, SUPPORT_THREAD_ROOM } from "./presence/room.js";
|
|
15
17
|
import { SUPPORT_MIGRATION_ORDER, isSupportCapability, support } from "./capability.js";
|
|
16
|
-
export { DEFAULT_CLASSIFY_MODEL, DEFAULT_SUPPORT_CATEGORIES, DEFAULT_SUPPORT_REPLIES, SUPPORT_ATTACHMENTS_TABLE, SUPPORT_CLASSIFICATIONS_TABLE, SUPPORT_CONTROL_PLANE_SCOPES, SUPPORT_FLAGS_TABLE, SUPPORT_MESSAGES_TABLE, SUPPORT_MIGRATION_ORDER, SUPPORT_SEARCH_TABLE, SUPPORT_THREADS_ARCHIVE_SCOPE, SUPPORT_THREADS_FLAG_SCOPE, SUPPORT_THREADS_READ_SCOPE, SUPPORT_THREADS_RECLASSIFY_SCOPE, SUPPORT_THREADS_REPLY_SCOPE, SUPPORT_THREADS_TABLE, SupportAiConfig, SupportAttachment, SupportAttachmentsConfig, SupportAuditActions, SupportClassification, SupportConfig, SupportGuardConfig, SupportMessage, SupportMessageDirection, SupportPriority, SupportReplyConfig, SupportReplySnippet, SupportSearchConfig, SupportSentiment, SupportThread, SupportThreadFlag, UNCATEGORIZED, defineSupportCategories, defineSupportReplies, isSupportCapability, support, supportDatabase };
|
|
18
|
+
export { DEFAULT_CLASSIFY_MODEL, DEFAULT_SUPPORT_CATEGORIES, DEFAULT_SUPPORT_REPLIES, SUPPORT_ASSIGNMENTS_TABLE, SUPPORT_ATTACHMENTS_TABLE, SUPPORT_CLASSIFICATIONS_TABLE, SUPPORT_CONTROL_PLANE_SCOPES, SUPPORT_FLAGS_TABLE, SUPPORT_MESSAGES_TABLE, SUPPORT_MIGRATION_ORDER, SUPPORT_SEARCH_TABLE, SUPPORT_THREADS_ARCHIVE_SCOPE, SUPPORT_THREADS_ASSIGN_SCOPE, SUPPORT_THREADS_FLAG_SCOPE, SUPPORT_THREADS_READ_SCOPE, SUPPORT_THREADS_RECLASSIFY_SCOPE, SUPPORT_THREADS_REPLY_SCOPE, SUPPORT_THREADS_TABLE, SUPPORT_THREAD_ACTIVITIES, SUPPORT_THREAD_ROOM, SupportAiConfig, SupportAssignment, SupportAssignmentActorType, SupportAttachment, SupportAttachmentsConfig, SupportAuditActions, SupportClassification, SupportConfig, SupportGuardConfig, SupportMessage, SupportMessageDirection, SupportPriority, SupportReplyConfig, SupportReplySnippet, SupportSearchConfig, SupportSentiment, SupportStaffConfig, SupportThread, SupportThreadFlag, UNASSIGNED, UNCATEGORIZED, defineSupportCategories, defineSupportReplies, isSupportCapability, support, supportDatabase };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import type { Migration } from "kysely/migration";
|
|
4
|
+
/**
|
|
5
|
+
* Who has a thread (#816): the current assignee on `pithy_support_threads`, and every change of it in a
|
|
6
|
+
* new append-only `pithy_support_assignments`.
|
|
7
|
+
*
|
|
8
|
+
* **A `0002`, appended, never folded into `0001`.** `@pithy-sh/support` has shipped, so its chain is
|
|
9
|
+
* history.
|
|
10
|
+
*
|
|
11
|
+
* **Four nullable columns and no backfill.** Every thread that exists when this runs has no assignee, and
|
|
12
|
+
* null is exactly that.
|
|
13
|
+
*
|
|
14
|
+
* **One index for the filter.** The inbox lists `archived`, newest first, and `assignee=<ref>` narrows it;
|
|
15
|
+
* `(assigneeRef, archived, lastMessageAt, id)` serves that page and its cursor the way
|
|
16
|
+
* `pithySupportThreadsArchivedIdx` serves the unfiltered one. `assignee=none` reads the unfiltered index
|
|
17
|
+
* and is a residual predicate on it.
|
|
18
|
+
*/
|
|
19
|
+
export declare const support_0002_assignment: Migration;
|
|
20
|
+
//# sourceMappingURL=0002_assignment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"0002_assignment.d.ts","sourceRoot":"","sources":["../../src/migrations/0002_assignment.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,uBAAuB,EAAE,SA2CrC,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
//#region src/migrations/0002_assignment.ts
|
|
4
|
+
/**
|
|
5
|
+
* Who has a thread (#816): the current assignee on `pithy_support_threads`, and every change of it in a
|
|
6
|
+
* new append-only `pithy_support_assignments`.
|
|
7
|
+
*
|
|
8
|
+
* **A `0002`, appended, never folded into `0001`.** `@pithy-sh/support` has shipped, so its chain is
|
|
9
|
+
* history.
|
|
10
|
+
*
|
|
11
|
+
* **Four nullable columns and no backfill.** Every thread that exists when this runs has no assignee, and
|
|
12
|
+
* null is exactly that.
|
|
13
|
+
*
|
|
14
|
+
* **One index for the filter.** The inbox lists `archived`, newest first, and `assignee=<ref>` narrows it;
|
|
15
|
+
* `(assigneeRef, archived, lastMessageAt, id)` serves that page and its cursor the way
|
|
16
|
+
* `pithySupportThreadsArchivedIdx` serves the unfiltered one. `assignee=none` reads the unfiltered index
|
|
17
|
+
* and is a residual predicate on it.
|
|
18
|
+
*/
|
|
19
|
+
const support_0002_assignment = {
|
|
20
|
+
async up(db) {
|
|
21
|
+
await db.schema.alterTable("pithySupportThreads").addColumn("assigneeRef", "text").execute();
|
|
22
|
+
await db.schema.alterTable("pithySupportThreads").addColumn("assigneeName", "text").execute();
|
|
23
|
+
await db.schema.alterTable("pithySupportThreads").addColumn("assignedAt", "integer").execute();
|
|
24
|
+
await db.schema.alterTable("pithySupportThreads").addColumn("assignedBy", "text").execute();
|
|
25
|
+
await db.schema.createIndex("pithySupportThreadsAssigneeIdx").on("pithySupportThreads").columns([
|
|
26
|
+
"assigneeRef",
|
|
27
|
+
"archived",
|
|
28
|
+
"lastMessageAt",
|
|
29
|
+
"id"
|
|
30
|
+
]).execute();
|
|
31
|
+
await db.schema.createTable("pithySupportAssignments").addColumn("id", "text", (c) => c.primaryKey()).addColumn("threadId", "text", (c) => c.notNull()).addColumn("assigneeRef", "text").addColumn("assigneeName", "text").addColumn("previousRef", "text").addColumn("previousName", "text").addColumn("actorType", "text", (c) => c.notNull()).addColumn("assignedBy", "text", (c) => c.notNull()).addColumn("note", "text").addColumn("createdAt", "integer", (c) => c.notNull()).execute();
|
|
32
|
+
await db.schema.createIndex("pithySupportAssignmentsThreadIdx").on("pithySupportAssignments").columns(["threadId", "createdAt"]).execute();
|
|
33
|
+
},
|
|
34
|
+
async down(db) {
|
|
35
|
+
await db.schema.dropIndex("pithySupportAssignmentsThreadIdx").execute();
|
|
36
|
+
await db.schema.dropTable("pithySupportAssignments").execute();
|
|
37
|
+
await db.schema.dropIndex("pithySupportThreadsAssigneeIdx").execute();
|
|
38
|
+
await db.schema.alterTable("pithySupportThreads").dropColumn("assignedBy").execute();
|
|
39
|
+
await db.schema.alterTable("pithySupportThreads").dropColumn("assignedAt").execute();
|
|
40
|
+
await db.schema.alterTable("pithySupportThreads").dropColumn("assigneeName").execute();
|
|
41
|
+
await db.schema.alterTable("pithySupportThreads").dropColumn("assigneeRef").execute();
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
//#endregion
|
|
45
|
+
export { support_0002_assignment };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import type { Migration } from "kysely/migration";
|
|
4
|
+
/**
|
|
5
|
+
* The semantic index's model stamps: one row per embedded message in `pithy_support_embeddings`.
|
|
6
|
+
*
|
|
7
|
+
* **Appended, and the messages table is not touched**: a released migration is never edited, and the stamp
|
|
8
|
+
* describes a derived index, not the mail. The table exists whether or not `search.semantic` is on, because the
|
|
9
|
+
* migration set must not vary with a config flag (`store/searchIndex.ts` says why); an empty table costs nothing.
|
|
10
|
+
*
|
|
11
|
+
* No index beyond the primary key. A reprocess page reads messages in id order and joins this on `messageId`,
|
|
12
|
+
* which the key serves.
|
|
13
|
+
*/
|
|
14
|
+
export declare const support_0003_embeddings: Migration;
|
|
15
|
+
//# sourceMappingURL=0003_embeddings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"0003_embeddings.d.ts","sourceRoot":"","sources":["../../src/migrations/0003_embeddings.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,EAAE,SAYrC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
//#region src/migrations/0003_embeddings.ts
|
|
4
|
+
/**
|
|
5
|
+
* The semantic index's model stamps: one row per embedded message in `pithy_support_embeddings`.
|
|
6
|
+
*
|
|
7
|
+
* **Appended, and the messages table is not touched**: a released migration is never edited, and the stamp
|
|
8
|
+
* describes a derived index, not the mail. The table exists whether or not `search.semantic` is on, because the
|
|
9
|
+
* migration set must not vary with a config flag (`store/searchIndex.ts` says why); an empty table costs nothing.
|
|
10
|
+
*
|
|
11
|
+
* No index beyond the primary key. A reprocess page reads messages in id order and joins this on `messageId`,
|
|
12
|
+
* which the key serves.
|
|
13
|
+
*/
|
|
14
|
+
const support_0003_embeddings = {
|
|
15
|
+
async up(db) {
|
|
16
|
+
await db.schema.createTable("pithySupportEmbeddings").addColumn("messageId", "text", (c) => c.primaryKey()).addColumn("model", "text", (c) => c.notNull()).addColumn("embeddedAt", "integer", (c) => c.notNull()).execute();
|
|
17
|
+
},
|
|
18
|
+
async down(db) {
|
|
19
|
+
await db.schema.dropTable("pithySupportEmbeddings").execute();
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
//#endregion
|
|
23
|
+
export { support_0003_embeddings };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import type { Migration } from "kysely/migration";
|
|
4
|
+
/**
|
|
5
|
+
* Every support migration, in order — the set the capability contributes and the one every test that
|
|
6
|
+
* needs today's schema runs. Append-only: a released chain is history.
|
|
7
|
+
*
|
|
8
|
+
* The full-text index is **not** here: it is a provisioned resource `pithy support provision` creates and
|
|
9
|
+
* drops (`store/searchIndex.ts`), so a config flag can never corrupt a migration set shared with every
|
|
10
|
+
* other capability in the database.
|
|
11
|
+
*/
|
|
12
|
+
export declare const SUPPORT_MIGRATIONS: Record<string, Migration>;
|
|
13
|
+
//# sourceMappingURL=set.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../src/migrations/set.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAKlD;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAIxD,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import { support_0001_threads } from "./0001_threads.js";
|
|
4
|
+
import { support_0002_assignment } from "./0002_assignment.js";
|
|
5
|
+
import { support_0003_embeddings } from "./0003_embeddings.js";
|
|
6
|
+
//#region src/migrations/set.ts
|
|
7
|
+
/**
|
|
8
|
+
* Every support migration, in order — the set the capability contributes and the one every test that
|
|
9
|
+
* needs today's schema runs. Append-only: a released chain is history.
|
|
10
|
+
*
|
|
11
|
+
* The full-text index is **not** here: it is a provisioned resource `pithy support provision` creates and
|
|
12
|
+
* drops (`store/searchIndex.ts`), so a config flag can never corrupt a migration set shared with every
|
|
13
|
+
* other capability in the database.
|
|
14
|
+
*/
|
|
15
|
+
const SUPPORT_MIGRATIONS = {
|
|
16
|
+
"0001_threads": support_0001_threads,
|
|
17
|
+
"0002_assignment": support_0002_assignment,
|
|
18
|
+
"0003_embeddings": support_0003_embeddings
|
|
19
|
+
};
|
|
20
|
+
//#endregion
|
|
21
|
+
export { SUPPORT_MIGRATIONS };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import type { PithyHonoEnv } from "@pithy-sh/core/src/capability/capability";
|
|
4
|
+
import { type PresenceDeclaration, type PresenceSessionGate } from "@pithy-sh/core/src/presence/declaration";
|
|
5
|
+
import type { Context } from "hono";
|
|
6
|
+
import type { SupportWiring } from "../capability";
|
|
7
|
+
import type { SupportStaffConfig } from "../config/config";
|
|
8
|
+
/**
|
|
9
|
+
* Who else has a support thread open (#816) — support's one room kind on core's presence seam (#815).
|
|
10
|
+
*
|
|
11
|
+
* Anyone who may read a thread may see who else has it open, so the room joins with the scope that already
|
|
12
|
+
* reads it, `support:threads:read`, and adds none of its own. A management client mints its ticket at
|
|
13
|
+
* `POST /control-plane/presence/tickets`; a signed-in user of the app mints one at
|
|
14
|
+
* `POST {basePath}/presence/tickets` when `support({ staff })` names a read power their role holds. The room
|
|
15
|
+
* holds nothing but who is here and writes nothing anywhere.
|
|
16
|
+
*/
|
|
17
|
+
/** The room kind: one room per thread, keyed by the thread's id. */
|
|
18
|
+
export declare const SUPPORT_THREAD_ROOM = "support.thread";
|
|
19
|
+
/**
|
|
20
|
+
* What a participant may announce. `viewing` first, because the first is what a participant joins as;
|
|
21
|
+
* `replying` is announced by the client when its reply form opens, and cleared when it closes.
|
|
22
|
+
*/
|
|
23
|
+
export declare const SUPPORT_THREAD_ACTIVITIES: readonly ["viewing", "replying"];
|
|
24
|
+
/** The account name a staff participant joins under, or null when it cannot be read. */
|
|
25
|
+
export type StaffName = (c: Context<PithyHonoEnv>, userId: string) => Promise<{
|
|
26
|
+
name?: string;
|
|
27
|
+
} | null>;
|
|
28
|
+
/**
|
|
29
|
+
* The session gate: the read power in the organization this request acts for, the same question the staff
|
|
30
|
+
* routes ask. Admits under the account's own name; with none to read, core falls back to the user id.
|
|
31
|
+
*/
|
|
32
|
+
export declare function staffPresenceGate(staff: SupportStaffConfig, nameOf: StaffName): PresenceSessionGate;
|
|
33
|
+
/** Support's presence declaration, built from its resolved mount and staff config. */
|
|
34
|
+
export declare function supportPresence(basePath: string, wiring: SupportWiring): PresenceDeclaration;
|
|
35
|
+
//# sourceMappingURL=room.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"room.d.ts","sourceRoot":"","sources":["../../src/presence/room.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0CAA0C,CAAC;AAC7E,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACzB,MAAM,yCAAyC,CAAC;AAGjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAM3D;;;;;;;;GAQG;AAEH,oEAAoE;AACpE,eAAO,MAAM,mBAAmB,mBAAmB,CAAC;AAEpD;;;GAGG;AACH,eAAO,MAAM,yBAAyB,YAAI,SAAS,EAAE,UAAU,CAAU,CAAC;AAE1E,wFAAwF;AACxF,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAAC;AAExG;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,SAAS,GAAG,mBAAmB,CAQnG;AAkBD,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,mBAAmB,CAqB5F"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import { supportPresenceRegistry } from "../secret/registry.js";
|
|
4
|
+
import { staffMay } from "../staff/staff.js";
|
|
5
|
+
import { resolveSubmitterAccount } from "../link/sender.js";
|
|
6
|
+
import { SUPPORT_THREADS_READ_SCOPE } from "../http/scopes.js";
|
|
7
|
+
import { PRESENCE_TICKET_KEY_SECRET } from "@pithy-sh/core/src/presence/declaration";
|
|
8
|
+
import { sharedSecretsStore } from "@pithy-sh/secrets/src/sharedSecretsStore";
|
|
9
|
+
//#region src/presence/room.ts
|
|
10
|
+
/**
|
|
11
|
+
* Who else has a support thread open (#816) — support's one room kind on core's presence seam (#815).
|
|
12
|
+
*
|
|
13
|
+
* Anyone who may read a thread may see who else has it open, so the room joins with the scope that already
|
|
14
|
+
* reads it, `support:threads:read`, and adds none of its own. A management client mints its ticket at
|
|
15
|
+
* `POST /control-plane/presence/tickets`; a signed-in user of the app mints one at
|
|
16
|
+
* `POST {basePath}/presence/tickets` when `support({ staff })` names a read power their role holds. The room
|
|
17
|
+
* holds nothing but who is here and writes nothing anywhere.
|
|
18
|
+
*/
|
|
19
|
+
/** The room kind: one room per thread, keyed by the thread's id. */
|
|
20
|
+
const SUPPORT_THREAD_ROOM = "support.thread";
|
|
21
|
+
/**
|
|
22
|
+
* What a participant may announce. `viewing` first, because the first is what a participant joins as;
|
|
23
|
+
* `replying` is announced by the client when its reply form opens, and cleared when it closes.
|
|
24
|
+
*/
|
|
25
|
+
const SUPPORT_THREAD_ACTIVITIES = ["viewing", "replying"];
|
|
26
|
+
/**
|
|
27
|
+
* The session gate: the read power in the organization this request acts for, the same question the staff
|
|
28
|
+
* routes ask. Admits under the account's own name; with none to read, core falls back to the user id.
|
|
29
|
+
*/
|
|
30
|
+
function staffPresenceGate(staff, nameOf) {
|
|
31
|
+
return async (c) => {
|
|
32
|
+
const userId = c.var.auth?.userId;
|
|
33
|
+
if (!userId) return null;
|
|
34
|
+
if (!staffMay(await c.var.actingOrganization(), staff, "readPower")) return null;
|
|
35
|
+
const account = await nameOf(c, userId);
|
|
36
|
+
return account?.name ? { name: account.name } : {};
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The ticket signing keys, read through `@pithy-sh/secrets` per request — the current version signs and
|
|
41
|
+
* every version still honored verifies, so a rotation never strands a socket mid-handshake.
|
|
42
|
+
*/
|
|
43
|
+
async function ticketKeys(env) {
|
|
44
|
+
const { currentVersion, versions } = (await sharedSecretsStore(env, supportPresenceRegistry)).getVersions(PRESENCE_TICKET_KEY_SECRET);
|
|
45
|
+
const current = versions[currentVersion];
|
|
46
|
+
return [...current === void 0 ? [] : [current], ...Object.entries(versions).filter(([version]) => version !== currentVersion).map(([, value]) => value)];
|
|
47
|
+
}
|
|
48
|
+
/** Support's presence declaration, built from its resolved mount and staff config. */
|
|
49
|
+
function supportPresence(basePath, wiring) {
|
|
50
|
+
const staff = wiring.config.staff;
|
|
51
|
+
return {
|
|
52
|
+
basePath,
|
|
53
|
+
ticketKey: ticketKeys,
|
|
54
|
+
rooms: [{
|
|
55
|
+
kind: SUPPORT_THREAD_ROOM,
|
|
56
|
+
scope: SUPPORT_THREADS_READ_SCOPE,
|
|
57
|
+
activities: SUPPORT_THREAD_ACTIVITIES,
|
|
58
|
+
...staff ? { session: staffPresenceGate(staff, async (c, userId) => {
|
|
59
|
+
const d1 = c.env.DB;
|
|
60
|
+
return d1 ? resolveSubmitterAccount(d1, userId, wiring.peers) : null;
|
|
61
|
+
}) } : {}
|
|
62
|
+
}]
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
66
|
+
export { SUPPORT_THREAD_ACTIVITIES, SUPPORT_THREAD_ROOM, staffPresenceGate, supportPresence };
|
|
@@ -96,6 +96,30 @@ export interface SupportProvisioner {
|
|
|
96
96
|
dropped: boolean;
|
|
97
97
|
repaired: boolean;
|
|
98
98
|
}>;
|
|
99
|
+
/**
|
|
100
|
+
* The semantic message index in this environment, **before** the worker that binds it is deployed:
|
|
101
|
+
* created when `search.semantic` is on and it does not exist yet, untouched otherwise. Before, because a
|
|
102
|
+
* deploy that binds an index nobody created fails. Idempotent — an index that exists is reused as-is, and
|
|
103
|
+
* one with a different shape is refused rather than silently queried in the wrong space.
|
|
104
|
+
*/
|
|
105
|
+
ensureSemanticIndex(env: ManagedEnvironment): Promise<{
|
|
106
|
+
indexName: string;
|
|
107
|
+
created: boolean;
|
|
108
|
+
}>;
|
|
109
|
+
/**
|
|
110
|
+
* The semantic message index in this environment, **after** the worker is deployed:
|
|
111
|
+
*
|
|
112
|
+
* - On, and holding nothing yet — `created` by this run, or holding no stamp while inbound mail exists, which
|
|
113
|
+
* is what a run that failed after creating it leaves: backfill it once, by starting the reprocess Workflow
|
|
114
|
+
* over every inbound message. An index holding any stamp is never re-embedded here — that is
|
|
115
|
+
* `pithy vector reprocess`.
|
|
116
|
+
* - Off: drop the index if it exists, and the model stamps with it, since every stamp now names a vector
|
|
117
|
+
* that is gone. After the deploy, because the worker that bound it no longer does.
|
|
118
|
+
*/
|
|
119
|
+
settleSemanticIndex(env: ManagedEnvironment, created: boolean): Promise<{
|
|
120
|
+
dropped: boolean;
|
|
121
|
+
backfilled: boolean;
|
|
122
|
+
}>;
|
|
99
123
|
/**
|
|
100
124
|
* Ensure the inbound Email Routing rule that delivers the support address to the app worker.
|
|
101
125
|
* Idempotent, keyed on the rule name. Returns `skipped: true` when no routing config was supplied.
|
|
@@ -122,6 +146,14 @@ export interface SupportProvisionResult {
|
|
|
122
146
|
dropped: boolean;
|
|
123
147
|
repaired: boolean;
|
|
124
148
|
}>;
|
|
149
|
+
/** What the semantic message index did, per environment — created and backfilled, dropped, or unchanged. */
|
|
150
|
+
semantic: Array<{
|
|
151
|
+
env: ManagedEnvironment;
|
|
152
|
+
indexName: string;
|
|
153
|
+
created: boolean;
|
|
154
|
+
dropped: boolean;
|
|
155
|
+
backfilled: boolean;
|
|
156
|
+
}>;
|
|
125
157
|
/** Whether the inbound routing rule was created, already present, or skipped. */
|
|
126
158
|
routing: {
|
|
127
159
|
created: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provisionSupport.d.ts","sourceRoot":"","sources":["../../src/provision/provisionSupport.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAKlF,OAAO,EAEL,KAAK,iBAAiB,EAEtB,KAAK,kBAAkB,EAExB,MAAM,6BAA6B,CAAC;AAGrC;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,kBAAkB,GAAG,MAAM,CAElF;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,kBAAkB,GAAG,MAAM,EAAE,CAIvF;AAED,uEAAuE;AACvE,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B;;;;;OAKG;IACH,YAAY,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAChF,sEAAsE;IACtE,YAAY,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD;;;;;;;;;;;;;;;OAeG;IACH,iBAAiB,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC/G;;;OAGG;IACH,iBAAiB,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACtE;AAED,kCAAkC;AAClC,MAAM,WAAW,sBAAsB;IACrC,uDAAuD;IACvD,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAC/D,iEAAiE;IACjE,YAAY,EAAE,kBAAkB,EAAE,CAAC;IACnC,sGAAsG;IACtG,MAAM,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,kBAAkB,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAClG,iFAAiF;IACjF,OAAO,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CACjD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,kBAAkB,EAC/B,YAAY,EAAE,oBAAoB,GAAG,SAAS,MAAM,EAAE,GACrD,OAAO,CAAC,sBAAsB,CAAC,
|
|
1
|
+
{"version":3,"file":"provisionSupport.d.ts","sourceRoot":"","sources":["../../src/provision/provisionSupport.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
import { SUPPORT_CAPABILITY, supportWorkflowRegistry } from "../workflows/specs.js";
|
|
4
|
+
import { resourceNames } from "@pithy-sh/core/src/naming/resourceNames";
|
|
4
5
|
import { GLOBAL_SCOPE } from "@pithy-sh/core/src/naming/environment";
|
|
5
6
|
import { resourceName } from "@pithy-sh/core/src/naming/resource";
|
|
6
|
-
import { resourceNames } from "@pithy-sh/core/src/naming/resourceNames";
|
|
7
7
|
import { hostWorkflowsFor } from "@pithy-sh/core/src/workflow/host";
|
|
8
8
|
import { assertSharedLeavesLast, deprovisionTarget, managedEnvironments } from "@pithy-sh/secrets/src/scope";
|
|
9
9
|
//#region src/provision/provisionSupport.ts
|
|
@@ -94,13 +94,20 @@ async function provisionSupport(provisioner, environments) {
|
|
|
94
94
|
await provisioner.preflight();
|
|
95
95
|
const bucket = await provisioner.ensureBucket();
|
|
96
96
|
const search = [];
|
|
97
|
+
const semantic = [];
|
|
97
98
|
const deployed = managedEnvironments(environments);
|
|
98
99
|
for (const env of deployed) {
|
|
100
|
+
const index = await provisioner.ensureSemanticIndex(env);
|
|
99
101
|
await provisioner.deployWorker(env);
|
|
100
102
|
search.push({
|
|
101
103
|
env,
|
|
102
104
|
...await provisioner.ensureSearchIndex(env)
|
|
103
105
|
});
|
|
106
|
+
semantic.push({
|
|
107
|
+
env,
|
|
108
|
+
...index,
|
|
109
|
+
...await provisioner.settleSemanticIndex(env, index.created)
|
|
110
|
+
});
|
|
104
111
|
}
|
|
105
112
|
return {
|
|
106
113
|
bucket,
|
|
@@ -109,7 +116,8 @@ async function provisionSupport(provisioner, environments) {
|
|
|
109
116
|
created: false,
|
|
110
117
|
skipped: true
|
|
111
118
|
},
|
|
112
|
-
search
|
|
119
|
+
search,
|
|
120
|
+
semantic
|
|
113
121
|
};
|
|
114
122
|
}
|
|
115
123
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveSupportConfig.d.ts","sourceRoot":"","sources":["../../src/provision/resolveSupportConfig.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAyC,KAAK,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACpH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"resolveSupportConfig.d.ts","sourceRoot":"","sources":["../../src/provision/resolveSupportConfig.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAyC,KAAK,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACpH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAItD;;;;;;;;;;;;;;;;;;GAkBG;AAEH,8FAA8F;AAC9F,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,GAAG,EAAE,kBAAkB,CAAC;IACxB;;;OAGG;IACH,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,gFAAgF;IAChF,aAAa,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,aAAa,EAAE,aAAa,CAAC;CAC9B;AAED,6CAA6C;AAC7C,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,oBAAoB,EAC9B,MAAM,EAAE,mBAAmB,GAC1B,oBAAoB,CA8BtB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
|
+
import { supportMessageIndex, supportMessageIndexName } from "../semantic/messageIndex.js";
|
|
3
4
|
import { SUPPORT_CAPABILITY, supportWorkflowRegistry } from "../workflows/specs.js";
|
|
4
5
|
import { hostWorkflowsFor, resolveWorkflowHost } from "@pithy-sh/core/src/workflow/host";
|
|
5
6
|
//#region src/provision/resolveSupportConfig.ts
|
|
@@ -7,13 +8,23 @@ import { hostWorkflowsFor, resolveWorkflowHost } from "@pithy-sh/core/src/workfl
|
|
|
7
8
|
function resolveSupportConfig(template, params) {
|
|
8
9
|
const feature = params.feature;
|
|
9
10
|
const { project, env } = params;
|
|
10
|
-
|
|
11
|
+
const index = supportMessageIndex(params.supportConfig.search);
|
|
12
|
+
const indexName = index ? supportMessageIndexName(project, env, feature) : void 0;
|
|
13
|
+
return resolveWorkflowHost(index && indexName ? {
|
|
14
|
+
...template,
|
|
15
|
+
vectorize: [{
|
|
16
|
+
binding: index.binding,
|
|
17
|
+
index_name: indexName,
|
|
18
|
+
remote: true
|
|
19
|
+
}]
|
|
20
|
+
} : template, {
|
|
11
21
|
project,
|
|
12
22
|
capability: SUPPORT_CAPABILITY,
|
|
13
23
|
env,
|
|
14
24
|
...feature ? { feature } : {},
|
|
15
25
|
databaseIds: { DB: params.appDatabaseId },
|
|
16
|
-
|
|
26
|
+
...index && indexName ? { vectorizeIndexNames: { [index.binding]: indexName } } : {},
|
|
27
|
+
remoteBindings: index ? ["AI", index.binding] : ["AI"],
|
|
17
28
|
vars: { SUPPORT_CONFIG: JSON.stringify(params.supportConfig) },
|
|
18
29
|
workflows: hostWorkflowsFor(supportWorkflowRegistry, {
|
|
19
30
|
project,
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import { type ErasingPurgeContribution } from "@pithy-sh/core/src/capability/purge";
|
|
4
|
+
/**
|
|
5
|
+
* What erasing one person means for `@pithy-sh/support` (#814): every thread they opened — linked to their account,
|
|
6
|
+
* or sent from their address and linked to no account — with every message in it, its attachments and raw mail in
|
|
7
|
+
* R2, its classifications, every operator's read and snooze state on it, and the history of who had it (#816). And
|
|
8
|
+
* what exporting them hands back.
|
|
9
|
+
*
|
|
10
|
+
* **A thread is the person's when it is linked to their account or came from their address.** An email thread from
|
|
11
|
+
* someone who never signed in carries no `userId`, only the address it came from; the address is read from the
|
|
12
|
+
* account that owns it (`PurgeContext.address`), so a thread sent before the person had an account is theirs too.
|
|
13
|
+
* The address side takes only a thread linked to no account: an address can move, and a thread linked to whoever
|
|
14
|
+
* held it before is that account's, never handed to the person who holds it now, nor erased with them.
|
|
15
|
+
*
|
|
16
|
+
* **The bytes go first, then the rows.** An attachment's row and a message's `rawKey` are the only things that name
|
|
17
|
+
* their objects, so a row deleted ahead of its object would leave bytes nothing can find. An R2 delete of a key
|
|
18
|
+
* already gone succeeds, so a retried step is **idempotent**, and a person with no threads finds nothing. Deleting
|
|
19
|
+
* a message drops it from the full-text index through the index's own triggers. Its vector in the semantic index
|
|
20
|
+
* is deleted by the message's id, stamped or not, before the message row that names it.
|
|
21
|
+
*
|
|
22
|
+
* **Who had a thread goes with the thread; who handed it over is the operator's.** The assignment history is a
|
|
23
|
+
* thread's own record — each change names the thread, who had it before and after, and the assigner's note about
|
|
24
|
+
* the person's request — so it is erased with the thread and exported with it, oldest first. Who made each change,
|
|
25
|
+
* `assignedBy`, is the operator's subject or a staff member's id, not the person's: the export leaves it out of the
|
|
26
|
+
* history and of the thread, as leaderboard leaves out a moderator, and the audit trail keeps every handover with its
|
|
27
|
+
* actor.
|
|
28
|
+
*
|
|
29
|
+
* **A staff member's own handovers, on threads that are not theirs, lose their id.** On the staff session door,
|
|
30
|
+
* `assignedBy` is the signed-in user's id, written onto a customer's thread and its history. Their purge sets it to
|
|
31
|
+
* `ERASED_ASSIGNER` wherever they acted as a user — every history row with `actorType = 'user'` and their id, and the
|
|
32
|
+
* thread's own `assignedBy` when that row made its current assignment — so the handover stays in the customer's
|
|
33
|
+
* record and stops naming them. A control-plane subject that happens to share the id is a client, not the person, and
|
|
34
|
+
* is left alone. Their export hands those handovers back as which thread, when, and how they were verified, never the
|
|
35
|
+
* assignee or the note, which are about the customer's request. Who **held** a thread is kept: an assignee is an
|
|
36
|
+
* opaque reference and a name the assigner chose, support cannot tell which reference is the person, and both go
|
|
37
|
+
* when the customer's thread does.
|
|
38
|
+
*/
|
|
39
|
+
/** What a purged staff member's id becomes on the handovers they made (#816). */
|
|
40
|
+
export declare const ERASED_ASSIGNER = "erased-user";
|
|
41
|
+
/** The one sentence the purge records with this step. */
|
|
42
|
+
export declare const SUPPORT_PURGE_SUMMARY = "Deletes every support thread the user opened, linked to their account or sent from their address and linked to no other account, with its messages, attachments, raw mail, classifications, read state and assignment history. On other people's threads, the handovers they made as a signed-in user lose their id; an assignee is an opaque reference the assigner named, so who held a thread stays until that thread goes.";
|
|
43
|
+
/** How the purge is composed. `semantic` is whether `search.semantic` is on, so the index must be reachable. */
|
|
44
|
+
export interface SupportPurgeOptions {
|
|
45
|
+
semantic?: boolean;
|
|
46
|
+
}
|
|
47
|
+
/** The user contribution `support()` declares. */
|
|
48
|
+
export declare function supportUserPurge(database?: string, options?: SupportPurgeOptions): ErasingPurgeContribution;
|
|
49
|
+
//# sourceMappingURL=contribution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contribution.d.ts","sourceRoot":"","sources":["../../src/purge/contribution.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,KAAK,wBAAwB,EAI9B,MAAM,qCAAqC,CAAC;AAqB7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,iFAAiF;AACjF,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAE7C,yDAAyD;AACzD,eAAO,MAAM,qBAAqB,maACgY,CAAC;AA2Dna,gHAAgH;AAChH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,kDAAkD;AAClD,wBAAgB,gBAAgB,CAAC,QAAQ,SAAO,EAAE,OAAO,GAAE,mBAAwB,GAAG,wBAAwB,CA4J7G"}
|