@maudecode/kanvil 0.5.1 → 0.6.1
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/apps/server/dist/{auth-Bm6cIseE.mjs → auth-CFjetlB4.mjs} +49 -7
- package/apps/server/dist/client.mjs +1 -1
- package/apps/server/dist/{config-CrJuk5mY.mjs → config-BQw6mPzE.mjs} +1 -1
- package/apps/server/dist/index.mjs +10 -5
- package/apps/server/dist/migrate.mjs +1 -1
- package/apps/server/dist/recover.mjs +3 -3
- package/apps/server/dist/{src-D80LNZKP.mjs → src-BaTNDJB7.mjs} +88 -3
- package/apps/server/drizzle/0039_intake_credential.sql +2 -0
- package/apps/server/drizzle/meta/0039_snapshot.json +7020 -0
- package/apps/server/drizzle/meta/_journal.json +7 -0
- package/apps/web/dist/assets/{CompositeItem-Tueq2VKR.js → CompositeItem-Dotj8JZL.js} +1 -1
- package/apps/web/dist/assets/{Trans-BgU0eWAX.js → Trans-CE4EAAY1.js} +1 -1
- package/apps/web/dist/assets/admin-settings-CO7nnD9T.js +1 -0
- package/apps/web/dist/assets/{archive-restore-CSpoH6mS.js → archive-restore-BMtgjFUu.js} +1 -1
- package/apps/web/dist/assets/az-AZ-R8_HFWJr.js +1 -0
- package/apps/web/dist/assets/{az-DUcDY8Bp.js → az-B-DxMc__.js} +1 -1
- package/apps/web/dist/assets/configuration-Bnt72HRu.js +1 -0
- package/apps/web/dist/assets/{corner-left-up-C3OGlXIB.js → corner-left-up-O4OsTW-L.js} +1 -1
- package/apps/web/dist/assets/{de-89C1V8Ut.js → de-Btbkq-aX.js} +1 -1
- package/apps/web/dist/assets/de-DE-BHgMj19Y.js +1 -0
- package/apps/web/dist/assets/default-DqsN66dq.js +56 -0
- package/apps/web/dist/assets/delivery-settings-Cji0N0m0.js +1 -0
- package/apps/web/dist/assets/{el-D6CICkhi.js → el-DBVEX16k.js} +1 -1
- package/apps/web/dist/assets/el-GR-CQFGM5Sr.js +1 -0
- package/apps/web/dist/assets/{ellipsis-lJJU8zB7.js → ellipsis-CvEPDi9V.js} +1 -1
- package/apps/web/dist/assets/{es-B20Izib2.js → es-CMJoxZBk.js} +1 -1
- package/apps/web/dist/assets/es-ES-DZkcRVA4.js +1 -0
- package/apps/web/dist/assets/{forms--87R7VQW.js → forms-DbfnnPg_.js} +1 -1
- package/apps/web/dist/assets/fr-FR-CRPAezXU.js +1 -0
- package/apps/web/dist/assets/{fr-DVlGnGsu.js → fr-OyEmYoRn.js} +1 -1
- package/apps/web/dist/assets/{hi-D1F5Pi_I.js → hi-CIgXSseB.js} +1 -1
- package/apps/web/dist/assets/hi-IN-2YFE4UQk.js +1 -0
- package/apps/web/dist/assets/{highlight-ygDJPvRy.js → highlight-B4K3yEEh.js} +1 -1
- package/apps/web/dist/assets/id-ID-B-J0_QIW.js +1 -0
- package/apps/web/dist/assets/{id-LESXKW7G.js → id-WV2oSAPB.js} +1 -1
- package/apps/web/dist/assets/index-BAnwOrh1.css +2 -0
- package/apps/web/dist/assets/index-nltuyQtq.js +17 -0
- package/apps/web/dist/assets/invitations-BTB8f2Xl.js +1 -0
- package/apps/web/dist/assets/{it-CgRGAs6u.js → it-BWSrRqus.js} +1 -1
- package/apps/web/dist/assets/it-IT-CJ0HYggO.js +1 -0
- package/apps/web/dist/assets/item-HmFuRZet.js +1 -0
- package/apps/web/dist/assets/{ja-B7arhzgX.js → ja-BtOHWvUJ.js} +1 -1
- package/apps/web/dist/assets/ja-JP-DDQS7D7b.js +1 -0
- package/apps/web/dist/assets/{ko-Ro_UonyA.js → ko-DAryK0HN.js} +1 -1
- package/apps/web/dist/assets/ko-KR-CkpoewEa.js +1 -0
- package/apps/web/dist/assets/label-settings-ssfEX2uR.js +1 -0
- package/apps/web/dist/assets/{markdown-blocks-toSPlHSc.js → markdown-blocks-B1kO6iku.js} +1 -1
- package/apps/web/dist/assets/member-directory-BA4ZT1qU.js +1 -0
- package/apps/web/dist/assets/{mk-DR3kmrIp.js → mk-DBbiGUk5.js} +1 -1
- package/apps/web/dist/assets/mk-MK-C0RhS6XR.js +1 -0
- package/apps/web/dist/assets/{nl-D3uRJJLT.js → nl-D4V-8WdF.js} +1 -1
- package/apps/web/dist/assets/nl-NL-BSKqlzcL.js +1 -0
- package/apps/web/dist/assets/{pl-CtzDOLdV.js → pl-C--QrxO0.js} +1 -1
- package/apps/web/dist/assets/pl-PL-CHz38SiU.js +1 -0
- package/apps/web/dist/assets/project-lifecycle-COZb9FqM.js +1 -0
- package/apps/web/dist/assets/project-settings-DwmTm9KA.js +1 -0
- package/apps/web/dist/assets/pt-BR-BotWHRiO.js +1 -0
- package/apps/web/dist/assets/{pt-BR-FarXHHuf.js → pt-BR-DvFVKpmO.js} +1 -1
- package/apps/web/dist/assets/{public-project-DGf3nkg2.js → public-project-B3hEkeCF.js} +1 -1
- package/apps/web/dist/assets/{rotate-ccw-Byx7O3RH.js → rotate-ccw-CB36Zu3L.js} +1 -1
- package/apps/web/dist/assets/ru-RU-DtOwNna6.js +1 -0
- package/apps/web/dist/assets/{ru-DHMEVxvB.js → ru-UmbPUOka.js} +1 -1
- package/apps/web/dist/assets/search-Cvetr1OK.js +85 -0
- package/apps/web/dist/assets/{send-DlGV2XQS.js → send-CJDct4Oj.js} +1 -1
- package/apps/web/dist/assets/settings-3IXm9lJ-.js +1 -0
- package/apps/web/dist/assets/{sliders-horizontal-CEHGGft_.js → sliders-horizontal-dmqWngxy.js} +1 -1
- package/apps/web/dist/assets/switch-BtScTpP9.js +1 -0
- package/apps/web/dist/assets/{table-2AEfwytk.js → table-byFokzo-.js} +1 -1
- package/apps/web/dist/assets/ticket-detail-C3YA3Hzc.js +2 -0
- package/apps/web/dist/assets/ticket-editor-CZnZQMG1.js +2 -0
- package/apps/web/dist/assets/ticket-list-BXUorfmj.js +6 -0
- package/apps/web/dist/assets/ticket-list-controls-BxGKCZMo.js +1 -0
- package/apps/web/dist/assets/{tr-CjdSDu0z.js → tr-CNpgQ4ka.js} +1 -1
- package/apps/web/dist/assets/tr-TR-CdG2alU2.js +1 -0
- package/apps/web/dist/assets/{uk-C8od6u_H.js → uk-MQoTXdpk.js} +1 -1
- package/apps/web/dist/assets/uk-UA-Ceu5gorw.js +1 -0
- package/apps/web/dist/assets/{upload-BeTAGU_W.js → upload-D1x_ib3B.js} +1 -1
- package/apps/web/dist/assets/{useQueries-BtRgTciJ.js → useQueries-BnlNCoy4.js} +1 -1
- package/apps/web/dist/assets/{vi-BwdBtgfS.js → vi-CEw4gTWc.js} +1 -1
- package/apps/web/dist/assets/vi-VN-CxshgV4W.js +1 -0
- package/apps/web/dist/assets/visual-editor-CpdMRn3e.js +208 -0
- package/apps/web/dist/assets/workspace-settings-BickBtZx.js +1 -0
- package/apps/web/dist/assets/{zh-CN-DM-UoFmL.js → zh-CN-ChzoXkfr.js} +1 -1
- package/apps/web/dist/assets/zh-CN-D7Yrjhd3.js +1 -0
- package/apps/web/dist/assets/zh-TW-DyF38kqx.js +1 -0
- package/apps/web/dist/assets/{zh-TW-q2nrwFjt.js → zh-TW-bWBKARrK.js} +1 -1
- package/apps/web/dist/index.html +9 -9
- package/docs/api.md +2 -2
- package/docs/mobile.md +67 -4
- package/docs/releasing.md +6 -4
- package/package.json +1 -1
- package/apps/web/dist/assets/admin-settings-Ckis3XJG.js +0 -1
- package/apps/web/dist/assets/az-AZ-bFxpMMZN.js +0 -1
- package/apps/web/dist/assets/de-DE-BeXI30Ll.js +0 -1
- package/apps/web/dist/assets/default-Dnep8Yat.js +0 -56
- package/apps/web/dist/assets/delivery-settings-cMldZ9K7.js +0 -1
- package/apps/web/dist/assets/el-GR-SgRHlWhY.js +0 -1
- package/apps/web/dist/assets/es-ES-BF1J5vap.js +0 -1
- package/apps/web/dist/assets/fr-FR-D_sldwf6.js +0 -1
- package/apps/web/dist/assets/hi-IN-CfOw4TWf.js +0 -1
- package/apps/web/dist/assets/id-ID-CLKtHO7Q.js +0 -1
- package/apps/web/dist/assets/index-Bn-MADyj.css +0 -2
- package/apps/web/dist/assets/index-Ds3IHeIi.js +0 -17
- package/apps/web/dist/assets/invitations-C5WbdDUQ.js +0 -1
- package/apps/web/dist/assets/it-IT-eVZNW5qX.js +0 -1
- package/apps/web/dist/assets/item-BD1Poxfs.js +0 -1
- package/apps/web/dist/assets/ja-JP-D96njn-P.js +0 -1
- package/apps/web/dist/assets/ko-KR-Bash_ieA.js +0 -1
- package/apps/web/dist/assets/label-settings-BaikCfal.js +0 -1
- package/apps/web/dist/assets/member-directory-BjUy1KuK.js +0 -1
- package/apps/web/dist/assets/mk-MK-BWQWGIRx.js +0 -1
- package/apps/web/dist/assets/nl-NL-D1tvo0Gd.js +0 -1
- package/apps/web/dist/assets/pl-PL-DNgGUEcQ.js +0 -1
- package/apps/web/dist/assets/project-lifecycle-BBHcRi6p.js +0 -1
- package/apps/web/dist/assets/project-settings-BaYuxYjg.js +0 -1
- package/apps/web/dist/assets/pt-BR-CZsUZQ6P.js +0 -1
- package/apps/web/dist/assets/ru-RU-4ew92YE_.js +0 -1
- package/apps/web/dist/assets/search-DwsPEC4E.js +0 -85
- package/apps/web/dist/assets/settings-C_sN8Y1h.js +0 -1
- package/apps/web/dist/assets/switch-B_rsZYBf.js +0 -1
- package/apps/web/dist/assets/ticket-detail-C2l8nwF-.js +0 -2
- package/apps/web/dist/assets/ticket-editor-B0UB98HS.js +0 -2
- package/apps/web/dist/assets/ticket-list-D_MHudj1.js +0 -6
- package/apps/web/dist/assets/ticket-list-controls-jKg4i-NA.js +0 -1
- package/apps/web/dist/assets/tr-TR-CM381XCw.js +0 -1
- package/apps/web/dist/assets/uk-UA-AeOiWCVo.js +0 -1
- package/apps/web/dist/assets/vi-VN-td08xXv9.js +0 -1
- package/apps/web/dist/assets/visual-editor-CzB_qwvB.js +0 -208
- package/apps/web/dist/assets/workspace-settings-DOr9j8X1.js +0 -1
- package/apps/web/dist/assets/zh-CN-D3dhEYLS.js +0 -1
- package/apps/web/dist/assets/zh-TW-CfhOEFo8.js +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as auth_schema_exports, c as oauthConsent, d as user, i as apikey, l as oauthRefreshToken, o as oauthAccessToken, r as account, s as oauthClient, u as session } from "./config-
|
|
2
|
-
import { $ as permissionLabels, A as hasAdminRole, At as workflowOrder, Bt as searchSettingsSchema, D as filterKey, Dt as ticketPredicates, E as eventSchema, Et as ticketImportSchema, F as isHexColor, Ft as instanceUpdateSchema, J as operationPermission, N as importSecretFields, Nt as authenticationPolicySchema, O as filterList, Ot as ticketSchema, P as invitationStatuses, Pt as brokerSettingsSchema, Q as parsePublicOutput, Rt as s3SettingsSchema, S as difficulties, St as states, T as eventLabels, Tt as ticketFilter, V as mentionScheme, X as parseCustomFieldFilter, Y as operations, Z as parseOutput, _ as deletedAccountName, _t as seededPermissions, at as publicOperations, b as destinationEventKeys, bt as stagedUploadLifetime, ct as repositoryProviderDefinitions, d as customFieldSchema, dt as resourceProvider, et as permissionScope, f as customFieldValue, ft as roleCategory, g as defaultWorkflow, gt as searchResultTypes, h as defaultOrder, ht as scopes, i as channelRouteAllows, it as projectSchema, jt as workspaceSchema, k as formatEvent, kt as ticketSummarySchema, l as credentialProjectsSchema, lt as repositoryProviders, m as defaultClaimMaxLeaseSeconds, mt as roles, n as attachmentLimit, nt as priorities, p as customFieldValueSchema, pt as roleLabels, r as channelKinds, rt as priorityLabels, s as closedStates, st as remoteKinds, t as ApiError, tt as permissions, u as customFieldFilterTokens, ut as repositorySecretFields, v as deliverySecretFields, vt as signInMethodLabels, w as eventCategories, wt as ticketExportFormat, x as destinationKinds, xt as stateLabels, y as deliverySettingsSchema, yt as snapshotSchema, z as isSeededRole, zt as searchAuthentication } from "./src-
|
|
1
|
+
import { a as auth_schema_exports, c as oauthConsent, d as user, i as apikey, l as oauthRefreshToken, o as oauthAccessToken, r as account, s as oauthClient, u as session } from "./config-BQw6mPzE.mjs";
|
|
2
|
+
import { $ as permissionLabels, A as hasAdminRole, At as workflowOrder, Bt as searchSettingsSchema, D as filterKey, Dt as ticketPredicates, E as eventSchema, Et as ticketImportSchema, F as isHexColor, Ft as instanceUpdateSchema, J as operationPermission, N as importSecretFields, Nt as authenticationPolicySchema, O as filterList, Ot as ticketSchema, P as invitationStatuses, Pt as brokerSettingsSchema, Q as parsePublicOutput, Rt as s3SettingsSchema, S as difficulties, St as states, T as eventLabels, Tt as ticketFilter, V as mentionScheme, X as parseCustomFieldFilter, Y as operations, Z as parseOutput, _ as deletedAccountName, _t as seededPermissions, at as publicOperations, b as destinationEventKeys, bt as stagedUploadLifetime, ct as repositoryProviderDefinitions, d as customFieldSchema, dt as resourceProvider, et as permissionScope, f as customFieldValue, ft as roleCategory, g as defaultWorkflow, gt as searchResultTypes, h as defaultOrder, ht as scopes, i as channelRouteAllows, it as projectSchema, jt as workspaceSchema, k as formatEvent, kt as ticketSummarySchema, l as credentialProjectsSchema, lt as repositoryProviders, m as defaultClaimMaxLeaseSeconds, mt as roles, n as attachmentLimit, nt as priorities, p as customFieldValueSchema, pt as roleLabels, r as channelKinds, rt as priorityLabels, s as closedStates, st as remoteKinds, t as ApiError, tt as permissions, u as customFieldFilterTokens, ut as repositorySecretFields, v as deliverySecretFields, vt as signInMethodLabels, w as eventCategories, wt as ticketExportFormat, x as destinationKinds, xt as stateLabels, y as deliverySettingsSchema, yt as snapshotSchema, z as isSeededRole, zt as searchAuthentication } from "./src-BaTNDJB7.mjs";
|
|
3
3
|
import { and, asc, count, desc, eq, getTableColumns, gt, ilike, inArray, isNotNull, isNull, lt, lte, ne, notInArray, or, sql } from "drizzle-orm";
|
|
4
4
|
import { alias, bigint, boolean, check, customType, foreignKey, index, integer, jsonb, pgTable, primaryKey, text, timestamp, unionAll, unique, uniqueIndex, uuid } from "drizzle-orm/pg-core";
|
|
5
5
|
import { z } from "zod";
|
|
@@ -218,6 +218,7 @@ const tickets = pgTable("tickets", {
|
|
|
218
218
|
automationReady: boolean("automation_ready").notNull().default(false),
|
|
219
219
|
claimRequired: boolean("claim_required").notNull().default(false),
|
|
220
220
|
holdReason: text("hold_reason"),
|
|
221
|
+
intakeCredentialId: text("intake_credential_id"),
|
|
221
222
|
startAt: timestamp("start_at", { withTimezone: true }),
|
|
222
223
|
dueAt: timestamp("due_at", { withTimezone: true }),
|
|
223
224
|
archived: boolean("archived").notNull().default(false),
|
|
@@ -233,6 +234,7 @@ const tickets = pgTable("tickets", {
|
|
|
233
234
|
index("ticket_parent").on(table.parentId),
|
|
234
235
|
index("ticket_project_position").on(table.projectId, table.position),
|
|
235
236
|
index("ticket_state").on(table.stateId),
|
|
237
|
+
index("ticket_intake_credential").on(table.intakeCredentialId).where(sql`${table.intakeCredentialId} IS NOT NULL`),
|
|
236
238
|
foreignKey({
|
|
237
239
|
name: "ticket_workflow_state",
|
|
238
240
|
columns: [
|
|
@@ -711,8 +713,7 @@ const createObjectStore = (configuration) => {
|
|
|
711
713
|
if (!create) throw new Error("Unsupported object storage provider");
|
|
712
714
|
return create(configuration.config);
|
|
713
715
|
};
|
|
714
|
-
|
|
715
|
-
//#region src/blob-storage.ts
|
|
716
|
+
const intakeAttachmentLifetime = 2592e6;
|
|
716
717
|
const stagedUploadCutoff = () => new Date(Date.now() - stagedUploadLifetime);
|
|
717
718
|
const digest$1 = (bytes) => createHash("sha256").update(bytes).digest("hex");
|
|
718
719
|
function decodeBlobData(value, limit) {
|
|
@@ -811,6 +812,31 @@ function createBlobStorage(database, instance, factory = createObjectStore, sche
|
|
|
811
812
|
});
|
|
812
813
|
}
|
|
813
814
|
async function collectBatch() {
|
|
815
|
+
await database.db.transaction(async (tx) => {
|
|
816
|
+
await tx.execute(sql`SELECT pg_advisory_xact_lock(7361080)`);
|
|
817
|
+
const expired = await tx.select({
|
|
818
|
+
attachment: attachments,
|
|
819
|
+
key: tickets.key,
|
|
820
|
+
title: tickets.title
|
|
821
|
+
}).from(attachments).innerJoin(tickets, eq(tickets.id, attachments.ticketId)).where(and(isNotNull(tickets.intakeCredentialId), eq(tickets.holdReason, intakeHoldReason), lt(attachments.createdAt, /* @__PURE__ */ new Date(Date.now() - intakeAttachmentLifetime)))).orderBy(asc(attachments.createdAt), asc(attachments.id)).limit(100);
|
|
822
|
+
if (!expired.length) return;
|
|
823
|
+
await tx.delete(attachments).where(inArray(attachments.id, expired.map(({ attachment }) => attachment.id)));
|
|
824
|
+
await appendEvents(tx, expired.map(({ attachment, key, title }) => ({
|
|
825
|
+
projectId: attachment.projectId,
|
|
826
|
+
ticketId: attachment.ticketId,
|
|
827
|
+
actorId: null,
|
|
828
|
+
type: "attachment.deleted",
|
|
829
|
+
data: {
|
|
830
|
+
attachmentId: attachment.id,
|
|
831
|
+
key,
|
|
832
|
+
title,
|
|
833
|
+
source: {
|
|
834
|
+
kind: "system",
|
|
835
|
+
id: "blob-cleanup"
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
})));
|
|
839
|
+
});
|
|
814
840
|
return database.db.transaction(async (tx) => {
|
|
815
841
|
await tx.delete(stagedUploads).where(lt(stagedUploads.createdAt, stagedUploadCutoff()));
|
|
816
842
|
const rows = await tx.select({ object: blobObjects }).from(blobObjects).leftJoin(attachments, eq(attachments.objectId, blobObjects.id)).leftJoin(profilePhotos, eq(profilePhotos.objectId, blobObjects.id)).leftJoin(stagedUploads, eq(stagedUploads.id, blobObjects.id)).leftJoin(projects, or(eq(projects.iconObjectId, blobObjects.id), eq(projects.backgroundObjectId, blobObjects.id))).where(and(isNull(attachments.id), isNull(profilePhotos.userId), isNull(stagedUploads.id), isNull(projects.id), lt(blobObjects.createdAt, /* @__PURE__ */ new Date(Date.now() - 864e5)))).limit(20).for("update", {
|
|
@@ -2453,7 +2479,8 @@ async function createTicketRow(ctx, input) {
|
|
|
2453
2479
|
customFields: intakeOnly(ctx.actor) ? {} : applyCustomFieldValues(await projectCustomFields(ctx), null, customFields),
|
|
2454
2480
|
...await allocateTicket(ctx),
|
|
2455
2481
|
id,
|
|
2456
|
-
createdBy: ctx.actor.id
|
|
2482
|
+
createdBy: ctx.actor.id,
|
|
2483
|
+
intakeCredentialId: intakeOnly(ctx.actor) ? ctx.actor.ownerId : null
|
|
2457
2484
|
}).returning());
|
|
2458
2485
|
await subscribe(ctx, row.projectId, row.id, [ctx.actor.id, row.assigneeId]);
|
|
2459
2486
|
return {
|
|
@@ -3495,6 +3522,14 @@ const collaborationHandlers = {
|
|
|
3495
3522
|
async upload_attachment(ctx, input) {
|
|
3496
3523
|
const ticket = await getTicket(ctx, input.ticketId);
|
|
3497
3524
|
const bytes = decodeBlobData(input.data, attachmentLimit);
|
|
3525
|
+
if (intakeOnly(ctx.actor)) {
|
|
3526
|
+
const stored = one(await ctx.db.select({
|
|
3527
|
+
files: sql`count(*) filter (where ${attachments.ticketId} = ${ticket.id})`.mapWith(Number),
|
|
3528
|
+
bytes: sql`coalesce(sum(${attachments.size}), 0)`.mapWith(Number)
|
|
3529
|
+
}).from(attachments).innerJoin(tickets, eq(tickets.id, attachments.ticketId)).where(and(eq(tickets.intakeCredentialId, ctx.actor.ownerId), eq(tickets.holdReason, intakeHoldReason))));
|
|
3530
|
+
if (stored.files >= 10) fail(409, "attachment_limit", `An intake credential can attach at most 10 files to a ticket`);
|
|
3531
|
+
if (stored.bytes + bytes.length > 1e9) fail(409, "attachment_limit", "This intake credential's untriaged tickets hold too many attachment bytes");
|
|
3532
|
+
}
|
|
3498
3533
|
const id = crypto.randomUUID();
|
|
3499
3534
|
await ctx.blobs.put(ctx.db, id, bytes, input.contentType);
|
|
3500
3535
|
const row = one(await ctx.db.insert(attachments).values({
|
|
@@ -6969,7 +7004,12 @@ const complete = (status) => closedStates.some((closed) => closed === status);
|
|
|
6969
7004
|
const intakeHoldReason = "Untrusted intake: human triage required";
|
|
6970
7005
|
const intakeQuarantined = (ticket) => ticket.holdReason === intakeHoldReason;
|
|
6971
7006
|
const intakeOnly = (actor) => actor.scopes.length > 0 && actor.scopes.every((scope) => scope === "intake");
|
|
6972
|
-
const
|
|
7007
|
+
const intakeOperations = /* @__PURE__ */ new Set([
|
|
7008
|
+
"create_ticket",
|
|
7009
|
+
"upload_attachment",
|
|
7010
|
+
"list_attachments"
|
|
7011
|
+
]);
|
|
7012
|
+
const hasScope = (actor, scope, operation) => intakeOnly(actor) ? !!operation && intakeOperations.has(operation) : actor.scopes.includes("admin") || actor.scopes.includes(scope) || scope === "read" && actor.scopes.some((value) => value !== "intake");
|
|
6973
7013
|
function requireScope(actor, scope, operation) {
|
|
6974
7014
|
if (!hasScope(actor, scope, operation)) fail(403, "insufficient_scope", `This credential requires ${scope} permission`);
|
|
6975
7015
|
}
|
|
@@ -7046,7 +7086,9 @@ async function context(db, actor, scope, projectId, workspaceId, permission = sc
|
|
|
7046
7086
|
};
|
|
7047
7087
|
}
|
|
7048
7088
|
async function getTicket(ctx, identifier) {
|
|
7049
|
-
|
|
7089
|
+
const ticket = one(await ctx.db.select().from(tickets).where(and(eq(tickets.projectId, project(ctx).id), ticketMatch(identifier))).limit(1));
|
|
7090
|
+
if (intakeOnly(ctx.actor) && !(ticket.intakeCredentialId === ctx.actor.ownerId && intakeQuarantined(ticket))) fail(404, "not_found", "The requested record was not found");
|
|
7091
|
+
return ticket;
|
|
7050
7092
|
}
|
|
7051
7093
|
const insertBatch = 1e3;
|
|
7052
7094
|
async function insertAll(rows, insert) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as errorSchema, Ct as streamErrorSchema, E as eventSchema, G as notificationReadInput, H as notificationIdsInput, K as notificationsSchema, Q as parsePublicOutput, U as notificationPreferencesInput, W as notificationPreferencesSchema, Y as operations, Z as parseOutput, a as checkpointSchema, at as publicOperations, q as okSchema, t as ApiError, yt as snapshotSchema } from "./src-
|
|
1
|
+
import { C as errorSchema, Ct as streamErrorSchema, E as eventSchema, G as notificationReadInput, H as notificationIdsInput, K as notificationsSchema, Q as parsePublicOutput, U as notificationPreferencesInput, W as notificationPreferencesSchema, Y as operations, Z as parseOutput, a as checkpointSchema, at as publicOperations, q as okSchema, t as ApiError, yt as snapshotSchema } from "./src-BaTNDJB7.mjs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { parseArgs } from "node:util";
|
|
4
4
|
import { constants } from "node:fs";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Bt as searchSettingsSchema, Pt as brokerSettingsSchema, Rt as s3SettingsSchema, m as defaultClaimMaxLeaseSeconds, o as claimLeaseSecondsSchema } from "./src-
|
|
1
|
+
import { Bt as searchSettingsSchema, Pt as brokerSettingsSchema, Rt as s3SettingsSchema, m as defaultClaimMaxLeaseSeconds, o as claimLeaseSecondsSchema } from "./src-BaTNDJB7.mjs";
|
|
2
2
|
import pg from "pg";
|
|
3
3
|
import { drizzle } from "drizzle-orm/node-postgres";
|
|
4
4
|
import { relations } from "drizzle-orm";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { a as auth_schema_exports, d as user$1, i as apikey, n as createDatabase, r as account, t as readConfig, u as session } from "./config-
|
|
2
|
-
import { A as hasAdminRole, B as memberSchema, Bt as searchSettingsSchema, C as errorSchema, Ft as instanceUpdateSchema, G as notificationReadInput, H as notificationIdsInput, I as isOperation, It as photoInputSchema, L as isPresetColor, Lt as photoResultSchema, M as importProviderDefinitions, Mt as adminInstanceSchema, Pt as brokerSettingsSchema, R as isPublicOperation, Rt as s3SettingsSchema, U as notificationPreferencesInput, W as notificationPreferencesSchema, Y as operations, at as publicOperations, c as credentialInput, g as defaultWorkflow, ht as scopes, j as importLimits, mt as roles, ot as pushDeviceInput, q as okSchema, s as closedStates, t as ApiError, wt as ticketExportFormat, xt as stateLabels } from "./src-
|
|
1
|
+
import { a as auth_schema_exports, d as user$1, i as apikey, n as createDatabase, r as account, t as readConfig, u as session } from "./config-BQw6mPzE.mjs";
|
|
2
|
+
import { A as hasAdminRole, B as memberSchema, Bt as searchSettingsSchema, C as errorSchema, Ft as instanceUpdateSchema, G as notificationReadInput, H as notificationIdsInput, I as isOperation, It as photoInputSchema, L as isPresetColor, Lt as photoResultSchema, M as importProviderDefinitions, Mt as adminInstanceSchema, Pt as brokerSettingsSchema, R as isPublicOperation, Rt as s3SettingsSchema, U as notificationPreferencesInput, W as notificationPreferencesSchema, Y as operations, at as publicOperations, c as credentialInput, g as defaultWorkflow, ht as scopes, j as importLimits, mt as roles, ot as pushDeviceInput, q as okSchema, s as closedStates, t as ApiError, wt as ticketExportFormat, xt as stateLabels } from "./src-BaTNDJB7.mjs";
|
|
3
3
|
import { t as migrateDatabase } from "./migrate-C9f4ozB4.mjs";
|
|
4
|
-
import { $ as stagedUploads, A as requireSession, B as attachmentContent, C as defaultSenders, D as createAccess, E as createHttpSender, F as decodeImage, G as events, H as blobObjects, I as imageResponse, J as notificationPreferences, L as stagedUploadCutoff, M as createTicketSearch, N as createTicketIndex, O as createWriteLimiter, P as createBlobStorage, Q as pushDevices, R as createObjectStore, S as receiveRepositoryWebhook, T as DeliveryError, U as deliveryCheckpoints, V as attachments, W as eventClock, X as profilePhotos, Y as notifications, Z as projects, _ as one, a as deliverySecrets, at as matchesOIDCBinding, b as requireRow, c as ownerBlocker, d as createDomain, et as storageBackends, f as errorEnvelope, g as notify, h as json, i as createInstance, it as workspaces, j as readCalendarFeed, k as requireInstanceAdmin, l as appendEvents, m as intakeOnly, n as emailCodesAvailable, nt as tickets, o as otherActiveAdministrator, p as fail, q as members, r as signInProviders, rt as workspaceMembers, s as ownedWorkspaces, t as createAuth, tt as subscriptions, u as assertVersion, v as reachable, w as deliverBatch, x as processImports, y as recipientColumns, z as createPollingJob } from "./auth-
|
|
4
|
+
import { $ as stagedUploads, A as requireSession, B as attachmentContent, C as defaultSenders, D as createAccess, E as createHttpSender, F as decodeImage, G as events, H as blobObjects, I as imageResponse, J as notificationPreferences, L as stagedUploadCutoff, M as createTicketSearch, N as createTicketIndex, O as createWriteLimiter, P as createBlobStorage, Q as pushDevices, R as createObjectStore, S as receiveRepositoryWebhook, T as DeliveryError, U as deliveryCheckpoints, V as attachments, W as eventClock, X as profilePhotos, Y as notifications, Z as projects, _ as one, a as deliverySecrets, at as matchesOIDCBinding, b as requireRow, c as ownerBlocker, d as createDomain, et as storageBackends, f as errorEnvelope, g as notify, h as json, i as createInstance, it as workspaces, j as readCalendarFeed, k as requireInstanceAdmin, l as appendEvents, m as intakeOnly, n as emailCodesAvailable, nt as tickets, o as otherActiveAdministrator, p as fail, q as members, r as signInProviders, rt as workspaceMembers, s as ownedWorkspaces, t as createAuth, tt as subscriptions, u as assertVersion, v as reachable, w as deliverBatch, x as processImports, y as recipientColumns, z as createPollingJob } from "./auth-CFjetlB4.mjs";
|
|
5
5
|
import { serve } from "@hono/node-server";
|
|
6
6
|
import pg from "pg";
|
|
7
7
|
import { drizzle } from "drizzle-orm/node-postgres";
|
|
@@ -359,7 +359,7 @@ function createCleanup() {
|
|
|
359
359
|
}
|
|
360
360
|
//#endregion
|
|
361
361
|
//#region src/version.ts
|
|
362
|
-
const applicationVersion = "0.
|
|
362
|
+
const applicationVersion = "0.6.1";
|
|
363
363
|
//#endregion
|
|
364
364
|
//#region src/realtime.ts
|
|
365
365
|
async function createRealtime(config) {
|
|
@@ -3436,10 +3436,15 @@ async function initializeApplication(database, config, adapters, cleanup) {
|
|
|
3436
3436
|
const result = await receiveRepositoryWebhook(domain, repositories, secrets, c.req.param("connectionId"), c.req.raw.headers, await c.req.text());
|
|
3437
3437
|
return c.json(result, result.outcome === "duplicate" ? 200 : 202);
|
|
3438
3438
|
});
|
|
3439
|
+
const intakeRoutes = [
|
|
3440
|
+
["POST", /^\/api\/v1\/projects\/[^/]+\/tickets$/],
|
|
3441
|
+
["POST", /^\/api\/v1\/projects\/[^/]+\/tickets\/[^/]+\/attachments$/],
|
|
3442
|
+
["GET", /^\/api\/v1\/projects\/[^/]+\/tickets\/[^/]+\/attachments$/]
|
|
3443
|
+
];
|
|
3439
3444
|
app.use("/api/v1/*", async (c, next) => {
|
|
3440
3445
|
access.checkOrigin(c.req.raw);
|
|
3441
3446
|
const actor = await access.authenticate(c.req.raw);
|
|
3442
|
-
if (intakeOnly(actor) && !(c.req.method ===
|
|
3447
|
+
if (intakeOnly(actor) && !intakeRoutes.some(([method, path]) => c.req.method === method && path.test(c.req.path))) fail(403, "insufficient_scope", "Intake credentials can only create tickets and attach files to them");
|
|
3443
3448
|
c.set("actor", actor);
|
|
3444
3449
|
if (!actor.machine && ![
|
|
3445
3450
|
"GET",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as createDatabase, t as readConfig } from "./config-
|
|
1
|
+
import { n as createDatabase, t as readConfig } from "./config-BQw6mPzE.mjs";
|
|
2
2
|
import { t as migrateDatabase } from "./migrate-C9f4ozB4.mjs";
|
|
3
3
|
//#region src/cli/migrate.ts
|
|
4
4
|
const database = createDatabase(readConfig());
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { d as user, n as createDatabase, r as account, t as readConfig, u as session } from "./config-
|
|
2
|
-
import { A as hasAdminRole } from "./src-
|
|
3
|
-
import { K as instanceSettings, p as fail, t as createAuth } from "./auth-
|
|
1
|
+
import { d as user, n as createDatabase, r as account, t as readConfig, u as session } from "./config-BQw6mPzE.mjs";
|
|
2
|
+
import { A as hasAdminRole } from "./src-BaTNDJB7.mjs";
|
|
3
|
+
import { K as instanceSettings, p as fail, t as createAuth } from "./auth-CFjetlB4.mjs";
|
|
4
4
|
import { and, eq, isNull, sql } from "drizzle-orm";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import { parseArgs } from "node:util";
|
|
@@ -1,5 +1,79 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import i18next from "i18next";
|
|
3
|
+
//#region ../../packages/contracts/src/icons.ts
|
|
4
|
+
const ticketSymbols = {
|
|
5
|
+
status: {
|
|
6
|
+
backlog: {
|
|
7
|
+
icon: "circle-dashed",
|
|
8
|
+
tone: "muted"
|
|
9
|
+
},
|
|
10
|
+
todo: {
|
|
11
|
+
icon: "circle",
|
|
12
|
+
tone: "muted"
|
|
13
|
+
},
|
|
14
|
+
in_progress: {
|
|
15
|
+
icon: "circle-dot",
|
|
16
|
+
tone: "accent"
|
|
17
|
+
},
|
|
18
|
+
in_review: {
|
|
19
|
+
icon: "clock",
|
|
20
|
+
tone: "warning"
|
|
21
|
+
},
|
|
22
|
+
done: {
|
|
23
|
+
icon: "circle-check",
|
|
24
|
+
tone: "success"
|
|
25
|
+
},
|
|
26
|
+
cancelled: {
|
|
27
|
+
icon: "circle-x",
|
|
28
|
+
tone: "muted"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
priority: {
|
|
32
|
+
urgent: {
|
|
33
|
+
icon: "octagon-alert",
|
|
34
|
+
tone: "danger"
|
|
35
|
+
},
|
|
36
|
+
high: {
|
|
37
|
+
icon: "arrow-up",
|
|
38
|
+
tone: "warning"
|
|
39
|
+
},
|
|
40
|
+
medium: {
|
|
41
|
+
icon: "equal",
|
|
42
|
+
tone: "foreground"
|
|
43
|
+
},
|
|
44
|
+
low: {
|
|
45
|
+
icon: "arrow-down",
|
|
46
|
+
tone: "accent"
|
|
47
|
+
},
|
|
48
|
+
none: {
|
|
49
|
+
icon: "minus",
|
|
50
|
+
tone: "muted"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
kind: {
|
|
54
|
+
feature: {
|
|
55
|
+
icon: "sparkles",
|
|
56
|
+
tone: "muted"
|
|
57
|
+
},
|
|
58
|
+
bug: {
|
|
59
|
+
icon: "bug",
|
|
60
|
+
tone: "muted"
|
|
61
|
+
},
|
|
62
|
+
chore: {
|
|
63
|
+
icon: "wrench",
|
|
64
|
+
tone: "muted"
|
|
65
|
+
},
|
|
66
|
+
research: {
|
|
67
|
+
icon: "flask-conical",
|
|
68
|
+
tone: "muted"
|
|
69
|
+
},
|
|
70
|
+
documentation: {
|
|
71
|
+
icon: "book-open",
|
|
72
|
+
tone: "muted"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
//#endregion
|
|
3
77
|
//#region ../../packages/contracts/src/instance.ts
|
|
4
78
|
const endpoint$1 = z.url({ protocol: /^https?$/ }).refine((value) => !/^https?:\/\/[^/]*@/.test(value) && !/[?#]/.test(value), "Use an HTTP(S) endpoint without embedded credentials");
|
|
5
79
|
const s3SettingsSchema = z.object({
|
|
@@ -930,6 +1004,7 @@ var en_US_default = {
|
|
|
930
1004
|
},
|
|
931
1005
|
ticket: {
|
|
932
1006
|
list: {
|
|
1007
|
+
manageViews: "Manage views",
|
|
933
1008
|
selectSection: "Select {{section}} tickets",
|
|
934
1009
|
expandSection: "Expand {{section}} tickets",
|
|
935
1010
|
collapseSection: "Collapse {{section}} tickets",
|
|
@@ -1058,6 +1133,7 @@ var en_US_default = {
|
|
|
1058
1133
|
noDue: "No due date"
|
|
1059
1134
|
},
|
|
1060
1135
|
filter: {
|
|
1136
|
+
add: "Add filter",
|
|
1061
1137
|
me: "Me",
|
|
1062
1138
|
searchTickets: "Search tickets",
|
|
1063
1139
|
searchTicketsPlaceholder: "Search tickets…",
|
|
@@ -1550,7 +1626,7 @@ var en_US_default = {
|
|
|
1550
1626
|
permission: {
|
|
1551
1627
|
intake: {
|
|
1552
1628
|
name: "Submit reports",
|
|
1553
|
-
description: "Create quarantined tickets only. Cannot read or edit tickets. Use alone."
|
|
1629
|
+
description: "Create quarantined tickets and attach files to them only. Cannot read or edit tickets. Use alone."
|
|
1554
1630
|
},
|
|
1555
1631
|
read: {
|
|
1556
1632
|
name: "Read tickets",
|
|
@@ -2497,6 +2573,9 @@ var en_US_default = {
|
|
|
2497
2573
|
}
|
|
2498
2574
|
},
|
|
2499
2575
|
native: {
|
|
2576
|
+
"navigation.projectButton": "{{project}} ⌄",
|
|
2577
|
+
"navigation.recentProjects": "Recent projects",
|
|
2578
|
+
"navigation.switchProject": "Switch workspace or project",
|
|
2500
2579
|
labelValue: "{{label}}: {{value}}",
|
|
2501
2580
|
ui: {
|
|
2502
2581
|
dismiss: "Dismiss",
|
|
@@ -2545,6 +2624,10 @@ var en_US_default = {
|
|
|
2545
2624
|
create: "Create project"
|
|
2546
2625
|
},
|
|
2547
2626
|
tickets: {
|
|
2627
|
+
options: "List options",
|
|
2628
|
+
expandAll: "Expand all sections",
|
|
2629
|
+
collapseAll: "Collapse all sections",
|
|
2630
|
+
select: "Select tickets",
|
|
2548
2631
|
search: "Search tickets",
|
|
2549
2632
|
searchPlaceholder: "Title, description, or key",
|
|
2550
2633
|
allStatuses: "All statuses",
|
|
@@ -2671,6 +2754,7 @@ var en_US_default = {
|
|
|
2671
2754
|
next: "Next activity"
|
|
2672
2755
|
},
|
|
2673
2756
|
inbox: {
|
|
2757
|
+
read: "Read",
|
|
2674
2758
|
markAllRead: "Mark all read",
|
|
2675
2759
|
empty: "No notifications"
|
|
2676
2760
|
},
|
|
@@ -2855,6 +2939,7 @@ const attachmentLimit = 1e7;
|
|
|
2855
2939
|
const stagedUploadLifetime = 864e5;
|
|
2856
2940
|
const stateLabels = labelTable(states, (value) => t(`common.status.${value}`));
|
|
2857
2941
|
const priorityLabels = labelTable(priorities, (value) => t(`common.priority.${value}`));
|
|
2942
|
+
ticketSymbols.status.backlog.tone, ticketSymbols.status.todo.tone, ticketSymbols.status.in_progress.tone, ticketSymbols.status.in_review.tone, ticketSymbols.status.done.tone, ticketSymbols.status.cancelled.tone;
|
|
2858
2943
|
const id = z.string().min(1).max(80);
|
|
2859
2944
|
const timestamp = z.iso.datetime();
|
|
2860
2945
|
const version = z.number().int().positive();
|
|
@@ -4635,7 +4720,7 @@ const operations = {
|
|
|
4635
4720
|
upload_attachment: op(ticketInput.extend({
|
|
4636
4721
|
...mutation,
|
|
4637
4722
|
...fileFields
|
|
4638
|
-
}).strict(), attachmentSchema, "POST", "/projects/{projectId}/tickets/{ticketId}/attachments", "write", "Upload up to 10 MB of base64-encoded bytes. The original filename is metadata, never a filesystem path."),
|
|
4723
|
+
}).strict(), attachmentSchema, "POST", "/projects/{projectId}/tickets/{ticketId}/attachments", "write", "Upload up to 10 MB of base64-encoded bytes. The original filename is metadata, never a filesystem path. An intake credential can attach up to 10 files to a quarantined ticket it created, within 1 GB across its quarantined tickets."),
|
|
4639
4724
|
stage_upload: op(projectInput.extend({
|
|
4640
4725
|
...mutation,
|
|
4641
4726
|
...fileFields
|
|
@@ -4644,7 +4729,7 @@ const operations = {
|
|
|
4644
4729
|
...mutation,
|
|
4645
4730
|
uploadId: z.uuid()
|
|
4646
4731
|
}).strict(), okSchema, "DELETE", "/projects/{projectId}/uploads/{uploadId}", "write", "Delete one of your unclaimed staged uploads and its bytes."),
|
|
4647
|
-
list_attachments: op(ticketInput, z.array(attachmentSchema), "GET", "/projects/{projectId}/tickets/{ticketId}/attachments", "read", "List authorized attachment metadata."),
|
|
4732
|
+
list_attachments: op(ticketInput, z.array(attachmentSchema), "GET", "/projects/{projectId}/tickets/{ticketId}/attachments", "read", "List authorized attachment metadata. An intake credential can list them on a quarantined ticket it created."),
|
|
4648
4733
|
delete_attachment: op(projectInput.extend({
|
|
4649
4734
|
...mutation,
|
|
4650
4735
|
attachmentId: z.uuid()
|